refactor(script): Split non-/tail logic
Split the script module into one tailing output module and one exec once module. Refs #281
This commit is contained in:
parent
611ed0e348
commit
ccddf052ec
17
include/modules/cmdscript.hpp
Normal file
17
include/modules/cmdscript.hpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "modules/script.hpp"
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
namespace modules {
|
||||||
|
class cmdscript_module : virtual public script_module {
|
||||||
|
public:
|
||||||
|
explicit cmdscript_module(const bar_settings&, string);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void process();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
POLYBAR_NS_END
|
@ -78,7 +78,7 @@ namespace modules {
|
|||||||
template <typename Impl>
|
template <typename Impl>
|
||||||
string module<Impl>::contents() {
|
string module<Impl>::contents() {
|
||||||
if (m_changed) {
|
if (m_changed) {
|
||||||
m_log.info("Rebuilding cache for '%s'...", name());
|
m_log.info("%s: Rebuilding cache", name());
|
||||||
m_cache = CAST_MOD(Impl)->get_output();
|
m_cache = CAST_MOD(Impl)->get_output();
|
||||||
m_changed = false;
|
m_changed = false;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "modules/backlight.hpp"
|
#include "modules/backlight.hpp"
|
||||||
#include "modules/battery.hpp"
|
#include "modules/battery.hpp"
|
||||||
#include "modules/bspwm.hpp"
|
#include "modules/bspwm.hpp"
|
||||||
|
#include "modules/cmdscript.hpp"
|
||||||
#include "modules/counter.hpp"
|
#include "modules/counter.hpp"
|
||||||
#include "modules/cpu.hpp"
|
#include "modules/cpu.hpp"
|
||||||
#include "modules/date.hpp"
|
#include "modules/date.hpp"
|
||||||
@ -14,6 +15,7 @@
|
|||||||
#include "modules/menu.hpp"
|
#include "modules/menu.hpp"
|
||||||
#include "modules/meta/base.hpp"
|
#include "modules/meta/base.hpp"
|
||||||
#include "modules/script.hpp"
|
#include "modules/script.hpp"
|
||||||
|
#include "modules/tailscript.hpp"
|
||||||
#include "modules/temperature.hpp"
|
#include "modules/temperature.hpp"
|
||||||
#include "modules/text.hpp"
|
#include "modules/text.hpp"
|
||||||
#include "modules/xbacklight.hpp"
|
#include "modules/xbacklight.hpp"
|
||||||
@ -46,52 +48,55 @@ POLYBAR_NS
|
|||||||
using namespace modules;
|
using namespace modules;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
template <typename... Args>
|
module_interface* make_module(string&& name, const bar_settings& bar, string module_name) {
|
||||||
module_interface* make_module(string&& name, Args&&... args) {
|
|
||||||
if (name == "internal/counter") {
|
if (name == "internal/counter") {
|
||||||
return new counter_module(forward<Args>(args)...);
|
return new counter_module(bar, move(module_name));
|
||||||
} else if (name == "internal/backlight") {
|
} else if (name == "internal/backlight") {
|
||||||
return new backlight_module(forward<Args>(args)...);
|
return new backlight_module(bar, move(module_name));
|
||||||
} else if (name == "internal/battery") {
|
} else if (name == "internal/battery") {
|
||||||
return new battery_module(forward<Args>(args)...);
|
return new battery_module(bar, move(module_name));
|
||||||
} else if (name == "internal/bspwm") {
|
} else if (name == "internal/bspwm") {
|
||||||
return new bspwm_module(forward<Args>(args)...);
|
return new bspwm_module(bar, move(module_name));
|
||||||
} else if (name == "internal/cpu") {
|
} else if (name == "internal/cpu") {
|
||||||
return new cpu_module(forward<Args>(args)...);
|
return new cpu_module(bar, move(module_name));
|
||||||
} else if (name == "internal/date") {
|
} else if (name == "internal/date") {
|
||||||
return new date_module(forward<Args>(args)...);
|
return new date_module(bar, move(module_name));
|
||||||
} else if (name == "internal/github") {
|
} else if (name == "internal/github") {
|
||||||
return new github_module(forward<Args>(args)...);
|
return new github_module(bar, move(module_name));
|
||||||
} else if (name == "internal/fs") {
|
} else if (name == "internal/fs") {
|
||||||
return new fs_module(forward<Args>(args)...);
|
return new fs_module(bar, move(module_name));
|
||||||
} else if (name == "internal/memory") {
|
} else if (name == "internal/memory") {
|
||||||
return new memory_module(forward<Args>(args)...);
|
return new memory_module(bar, move(module_name));
|
||||||
} else if (name == "internal/i3") {
|
} else if (name == "internal/i3") {
|
||||||
return new i3_module(forward<Args>(args)...);
|
return new i3_module(bar, move(module_name));
|
||||||
} else if (name == "internal/mpd") {
|
} else if (name == "internal/mpd") {
|
||||||
return new mpd_module(forward<Args>(args)...);
|
return new mpd_module(bar, move(module_name));
|
||||||
} else if (name == "internal/volume") {
|
} else if (name == "internal/volume") {
|
||||||
return new volume_module(forward<Args>(args)...);
|
return new volume_module(bar, move(module_name));
|
||||||
} else if (name == "internal/network") {
|
} else if (name == "internal/network") {
|
||||||
return new network_module(forward<Args>(args)...);
|
return new network_module(bar, move(module_name));
|
||||||
} else if (name == "internal/temperature") {
|
} else if (name == "internal/temperature") {
|
||||||
return new temperature_module(forward<Args>(args)...);
|
return new temperature_module(bar, move(module_name));
|
||||||
} else if (name == "internal/xbacklight") {
|
} else if (name == "internal/xbacklight") {
|
||||||
return new xbacklight_module(forward<Args>(args)...);
|
return new xbacklight_module(bar, move(module_name));
|
||||||
} else if (name == "internal/xkeyboard") {
|
} else if (name == "internal/xkeyboard") {
|
||||||
return new xkeyboard_module(forward<Args>(args)...);
|
return new xkeyboard_module(bar, move(module_name));
|
||||||
} else if (name == "internal/xwindow") {
|
} else if (name == "internal/xwindow") {
|
||||||
return new xwindow_module(forward<Args>(args)...);
|
return new xwindow_module(bar, move(module_name));
|
||||||
} else if (name == "internal/xworkspaces") {
|
} else if (name == "internal/xworkspaces") {
|
||||||
return new xworkspaces_module(forward<Args>(args)...);
|
return new xworkspaces_module(bar, move(module_name));
|
||||||
} else if (name == "custom/text") {
|
} else if (name == "custom/text") {
|
||||||
return new text_module(forward<Args>(args)...);
|
return new text_module(bar, move(module_name));
|
||||||
} else if (name == "custom/script") {
|
} else if (name == "custom/script") {
|
||||||
return new script_module(forward<Args>(args)...);
|
if (config::make().get<bool>("module/" + module_name, "tail", false)) {
|
||||||
|
return new tailscript_module(bar, move(module_name));
|
||||||
|
} else {
|
||||||
|
return new cmdscript_module(bar, move(module_name));
|
||||||
|
}
|
||||||
} else if (name == "custom/menu") {
|
} else if (name == "custom/menu") {
|
||||||
return new menu_module(forward<Args>(args)...);
|
return new menu_module(bar, move(module_name));
|
||||||
} else if (name == "custom/ipc") {
|
} else if (name == "custom/ipc") {
|
||||||
return new ipc_module(forward<Args>(args)...);
|
return new ipc_module(bar, move(module_name));
|
||||||
} else {
|
} else {
|
||||||
throw application_error("Unknown module: " + name);
|
throw application_error("Unknown module: " + name);
|
||||||
}
|
}
|
||||||
|
@ -1,41 +1,32 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <chrono>
|
#include "modules/meta/base.hpp"
|
||||||
|
|
||||||
#include "modules/meta/event_module.hpp"
|
|
||||||
#include "utils/command.hpp"
|
#include "utils/command.hpp"
|
||||||
|
#include "utils/io.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
namespace chrono = std::chrono;
|
|
||||||
|
|
||||||
#define OUTPUT_ACTION(BUTTON) \
|
|
||||||
if (!m_actions[BUTTON].empty()) \
|
|
||||||
m_builder->cmd(BUTTON, string_util::replace_all(m_actions[BUTTON], "%counter%", counter_str))
|
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
/**
|
class script_module : public module<script_module> {
|
||||||
* TODO: Split into timed-/streaming modules
|
|
||||||
*/
|
|
||||||
class script_module : public event_module<script_module> {
|
|
||||||
public:
|
public:
|
||||||
explicit script_module(const bar_settings&, string);
|
explicit script_module(const bar_settings&, string);
|
||||||
|
virtual ~script_module() {}
|
||||||
|
|
||||||
|
virtual void start();
|
||||||
|
virtual void stop();
|
||||||
|
|
||||||
void stop();
|
|
||||||
void idle();
|
|
||||||
bool has_event();
|
|
||||||
bool update();
|
|
||||||
string get_output();
|
string get_output();
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void process() = 0;
|
||||||
|
|
||||||
static constexpr const char* TAG_OUTPUT{"<output>"};
|
static constexpr const char* TAG_OUTPUT{"<output>"};
|
||||||
static constexpr const char* TAG_LABEL{"<label>"};
|
static constexpr const char* TAG_LABEL{"<label>"};
|
||||||
|
|
||||||
unique_ptr<command> m_command;
|
unique_ptr<command> m_command;
|
||||||
|
|
||||||
string m_exec;
|
string m_exec;
|
||||||
bool m_tail{false};
|
|
||||||
chrono::duration<double> m_interval{0};
|
chrono::duration<double> m_interval{0};
|
||||||
map<mousebtn, string> m_actions;
|
map<mousebtn, string> m_actions;
|
||||||
|
|
||||||
@ -48,6 +39,8 @@ namespace modules {
|
|||||||
size_t m_maxlen{0};
|
size_t m_maxlen{0};
|
||||||
// @deprecated
|
// @deprecated
|
||||||
bool m_ellipsis{true};
|
bool m_ellipsis{true};
|
||||||
|
|
||||||
|
bool m_stopping{false};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
include/modules/tailscript.hpp
Normal file
17
include/modules/tailscript.hpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "modules/script.hpp"
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
namespace modules {
|
||||||
|
class tailscript_module : virtual public script_module {
|
||||||
|
public:
|
||||||
|
explicit tailscript_module(const bar_settings&, string);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void process();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
POLYBAR_NS_END
|
@ -28,7 +28,7 @@ class file_ptr {
|
|||||||
class file_descriptor {
|
class file_descriptor {
|
||||||
public:
|
public:
|
||||||
explicit file_descriptor(const string& path, int flags = 0);
|
explicit file_descriptor(const string& path, int flags = 0);
|
||||||
explicit file_descriptor(int fd);
|
explicit file_descriptor(int fd, bool autoclose = true);
|
||||||
~file_descriptor();
|
~file_descriptor();
|
||||||
|
|
||||||
file_descriptor& operator=(const int);
|
file_descriptor& operator=(const int);
|
||||||
@ -44,13 +44,18 @@ class file_descriptor {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
int m_fd{-1};
|
int m_fd{-1};
|
||||||
|
bool m_autoclose{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
class fd_streambuf : public std::streambuf {
|
class fd_streambuf : public std::streambuf {
|
||||||
public:
|
public:
|
||||||
using traits_type = std::streambuf::traits_type;
|
using traits_type = std::streambuf::traits_type;
|
||||||
|
|
||||||
explicit fd_streambuf(int fd);
|
template <typename... Args>
|
||||||
|
explicit fd_streambuf(Args&&... args) : m_fd(forward<Args>(args)...) {
|
||||||
|
setg(m_in, m_in, m_in);
|
||||||
|
setp(m_out, m_out + sizeof(m_in));
|
||||||
|
}
|
||||||
~fd_streambuf();
|
~fd_streambuf();
|
||||||
|
|
||||||
explicit operator int();
|
explicit operator int();
|
||||||
@ -75,7 +80,8 @@ class fd_stream : public StreamType {
|
|||||||
public:
|
public:
|
||||||
using type = fd_stream<StreamType>;
|
using type = fd_stream<StreamType>;
|
||||||
|
|
||||||
explicit fd_stream(int fd) : m_buf(fd) {
|
template <typename... Args>
|
||||||
|
explicit fd_stream(Args&&... args) : m_buf(forward<Args>(args)...) {
|
||||||
StreamType::rdbuf(&m_buf);
|
StreamType::rdbuf(&m_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +101,7 @@ namespace file_util {
|
|||||||
bool exists(const string& filename);
|
bool exists(const string& filename);
|
||||||
string pick(const vector<string>& filenames);
|
string pick(const vector<string>& filenames);
|
||||||
string contents(const string& filename);
|
string contents(const string& filename);
|
||||||
bool is_fifo(string filename);
|
bool is_fifo(const string& filename);
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
decltype(auto) make_file_descriptor(Args&&... args) {
|
decltype(auto) make_file_descriptor(Args&&... args) {
|
||||||
|
@ -5,12 +5,10 @@
|
|||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
namespace io_util {
|
namespace io_util {
|
||||||
string read(int read_fd, int bytes_to_read, int& bytes_read_loc, int& status_loc);
|
string read(int read_fd, size_t bytes_to_read);
|
||||||
string read(int read_fd, int bytes_to_read = -1);
|
|
||||||
string readline(int read_fd, int& bytes_read);
|
|
||||||
string readline(int read_fd);
|
string readline(int read_fd);
|
||||||
|
|
||||||
size_t write(int write_fd, const string& data);
|
size_t write(int write_fd, size_t bytes_to_write, const string& data);
|
||||||
size_t writeline(int write_fd, const string& data);
|
size_t writeline(int write_fd, const string& data);
|
||||||
|
|
||||||
void tail(int read_fd, const function<void(string)>& callback);
|
void tail(int read_fd, const function<void(string)>& callback);
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "utils/env.hpp"
|
#include "utils/env.hpp"
|
||||||
#include "utils/file.hpp"
|
#include "utils/file.hpp"
|
||||||
#include "utils/inotify.hpp"
|
#include "utils/inotify.hpp"
|
||||||
|
#include "utils/io.hpp"
|
||||||
#include "utils/process.hpp"
|
#include "utils/process.hpp"
|
||||||
#include "x11/connection.hpp"
|
#include "x11/connection.hpp"
|
||||||
#include "x11/tray_manager.hpp"
|
#include "x11/tray_manager.hpp"
|
||||||
@ -20,6 +21,7 @@
|
|||||||
using namespace polybar;
|
using namespace polybar;
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
// std::cout << x << std::Endl;
|
||||||
// clang-format off
|
// clang-format off
|
||||||
const command_line::options opts{
|
const command_line::options opts{
|
||||||
command_line::option{"-h", "--help", "Show help options"},
|
command_line::option{"-h", "--help", "Show help options"},
|
||||||
|
38
src/modules/cmdscript.cpp
Normal file
38
src/modules/cmdscript.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "modules/cmdscript.hpp"
|
||||||
|
#include "drawtypes/label.hpp"
|
||||||
|
|
||||||
|
#include "modules/meta/base.inl"
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
namespace modules {
|
||||||
|
cmdscript_module::cmdscript_module(const bar_settings& bar, string name_) : script_module(bar, move(name_)) {
|
||||||
|
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", 5s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmdscript_module::process() {
|
||||||
|
if (!m_updatelock.try_lock()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::unique_lock<mutex> guard(m_updatelock, std::adopt_lock);
|
||||||
|
auto exec = string_util::replace_all(m_exec, "%counter%", to_string(++m_counter));
|
||||||
|
m_log.info("%s: Invoking shell command: \"%s\"", name(), exec);
|
||||||
|
m_command = command_util::make_command(exec);
|
||||||
|
m_command->exec(true);
|
||||||
|
} catch (const exception& err) {
|
||||||
|
m_log.err("%s: %s", name(), err.what());
|
||||||
|
throw module_error("Failed to execute command, stopping module...");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_output = m_command->readline()) != m_prev) {
|
||||||
|
broadcast();
|
||||||
|
m_prev = m_output;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(std::max(m_command->get_exit_status() == 0 ? m_interval : 1s, m_interval));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
POLYBAR_NS_END
|
@ -8,12 +8,11 @@ POLYBAR_NS
|
|||||||
namespace modules {
|
namespace modules {
|
||||||
template class module<script_module>;
|
template class module<script_module>;
|
||||||
|
|
||||||
script_module::script_module(const bar_settings& bar, string name_) : event_module<script_module>(bar, move(name_)) {
|
script_module::script_module(const bar_settings& bar, string name_) : module<script_module>(bar, move(name_)) {
|
||||||
m_exec = m_conf.get(name(), "exec", m_exec);
|
m_exec = m_conf.get(name(), "exec", m_exec);
|
||||||
m_tail = m_conf.get(name(), "tail", m_tail);
|
|
||||||
m_maxlen = m_conf.get(name(), "maxlen", m_maxlen);
|
m_maxlen = m_conf.get(name(), "maxlen", m_maxlen);
|
||||||
m_ellipsis = m_conf.get(name(), "ellipsis", m_ellipsis);
|
m_ellipsis = m_conf.get(name(), "ellipsis", m_ellipsis);
|
||||||
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", m_tail ? 0s : 5s);
|
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", 5s);
|
||||||
|
|
||||||
m_conf.warn_deprecated(
|
m_conf.warn_deprecated(
|
||||||
name(), "maxlen", "\"format = <label>\" and \"label = %output:0:" + to_string(m_maxlen) + "%\"");
|
name(), "maxlen", "\"format = <label>\" and \"label = %output:0:" + to_string(m_maxlen) + "%\"");
|
||||||
@ -33,70 +32,32 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void script_module::stop() {
|
void script_module::start() {
|
||||||
m_updatelock.unlock();
|
m_mainthread = thread([this] {
|
||||||
event_module::stop();
|
try {
|
||||||
|
while (running() && !m_stopping) {
|
||||||
|
this->process();
|
||||||
|
}
|
||||||
|
} catch (const exception& err) {
|
||||||
|
halt(err.what());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (m_command && m_command->is_running()) {
|
void script_module::stop() {
|
||||||
m_log.warn("%s: Stopping shell command", name());
|
std::lock_guard<mutex> guard(m_updatelock, std::adopt_lock);
|
||||||
|
|
||||||
|
m_stopping = true;
|
||||||
|
this->wakeup();
|
||||||
|
|
||||||
|
if (m_command) {
|
||||||
|
if (m_command->is_running()) {
|
||||||
|
m_log.warn("%s: Stopping shell command", name());
|
||||||
|
}
|
||||||
m_command->terminate();
|
m_command->terminate();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void script_module::idle() {
|
this->module::stop();
|
||||||
if (!m_tail) {
|
|
||||||
sleep(m_interval);
|
|
||||||
} else if (!m_command || !m_command->is_running()) {
|
|
||||||
sleep(m_interval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool script_module::has_event() {
|
|
||||||
if (!m_tail) {
|
|
||||||
return true;
|
|
||||||
} else if (!m_command || !m_command->is_running()) {
|
|
||||||
try {
|
|
||||||
string exec{string_util::replace_all(m_exec, "%counter%", to_string(++m_counter))};
|
|
||||||
m_log.info("%s: Invoking shell command: \"%s\"", name(), exec);
|
|
||||||
m_command = command_util::make_command(move(exec));
|
|
||||||
m_command->exec(false);
|
|
||||||
} catch (const std::exception& err) {
|
|
||||||
m_log.err("%s: %s", name(), err.what());
|
|
||||||
throw module_error("Failed to execute tail command, stopping module...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_command || (m_output = m_command->readline()) == m_prev) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_prev = m_output;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool script_module::update() {
|
|
||||||
if (m_tail) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
auto exec = string_util::replace_all(m_exec, "%counter%", to_string(++m_counter));
|
|
||||||
m_log.info("%s: Executing \"%s\"", name(), exec);
|
|
||||||
m_command = command_util::make_command(exec);
|
|
||||||
m_command->exec();
|
|
||||||
m_command->tail([&](string output) { m_output = output; });
|
|
||||||
} catch (const std::exception& err) {
|
|
||||||
m_log.err("%s: %s", name(), err.what());
|
|
||||||
throw module_error("Failed to execute command, stopping module...");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_output == m_prev) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_prev = m_output;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string script_module::get_output() {
|
string script_module::get_output() {
|
||||||
@ -117,11 +78,23 @@ namespace modules {
|
|||||||
auto counter_str = to_string(m_counter);
|
auto counter_str = to_string(m_counter);
|
||||||
string output{module::get_output()};
|
string output{module::get_output()};
|
||||||
|
|
||||||
OUTPUT_ACTION(mousebtn::LEFT);
|
if (!m_actions[mousebtn::LEFT].empty()) {
|
||||||
OUTPUT_ACTION(mousebtn::MIDDLE);
|
m_builder->cmd(mousebtn::LEFT, string_util::replace_all(m_actions[mousebtn::LEFT], "%counter%", counter_str));
|
||||||
OUTPUT_ACTION(mousebtn::RIGHT);
|
}
|
||||||
OUTPUT_ACTION(mousebtn::SCROLL_UP);
|
if (!m_actions[mousebtn::MIDDLE].empty()) {
|
||||||
OUTPUT_ACTION(mousebtn::SCROLL_DOWN);
|
m_builder->cmd(mousebtn::MIDDLE, string_util::replace_all(m_actions[mousebtn::MIDDLE], "%counter%", counter_str));
|
||||||
|
}
|
||||||
|
if (!m_actions[mousebtn::RIGHT].empty()) {
|
||||||
|
m_builder->cmd(mousebtn::RIGHT, string_util::replace_all(m_actions[mousebtn::RIGHT], "%counter%", counter_str));
|
||||||
|
}
|
||||||
|
if (!m_actions[mousebtn::SCROLL_UP].empty()) {
|
||||||
|
m_builder->cmd(
|
||||||
|
mousebtn::SCROLL_UP, string_util::replace_all(m_actions[mousebtn::SCROLL_UP], "%counter%", counter_str));
|
||||||
|
}
|
||||||
|
if (!m_actions[mousebtn::SCROLL_DOWN].empty()) {
|
||||||
|
m_builder->cmd(
|
||||||
|
mousebtn::SCROLL_DOWN, string_util::replace_all(m_actions[mousebtn::SCROLL_DOWN], "%counter%", counter_str));
|
||||||
|
}
|
||||||
|
|
||||||
m_builder->append(output);
|
m_builder->append(output);
|
||||||
|
|
||||||
|
50
src/modules/tailscript.cpp
Normal file
50
src/modules/tailscript.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "modules/tailscript.hpp"
|
||||||
|
#include "drawtypes/label.hpp"
|
||||||
|
|
||||||
|
#include "modules/meta/base.inl"
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
namespace modules {
|
||||||
|
tailscript_module::tailscript_module(const bar_settings& bar, string name_) : script_module(bar, move(name_)) {
|
||||||
|
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", 0s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tailscript_module::process() {
|
||||||
|
if (!m_updatelock.try_lock()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock<mutex> guard(m_updatelock, std::adopt_lock);
|
||||||
|
|
||||||
|
if (!m_command || !m_command->is_running()) {
|
||||||
|
string exec{string_util::replace_all(m_exec, "%counter%", to_string(++m_counter))};
|
||||||
|
m_log.info("%s: Invoking shell command: \"%s\"", name(), exec);
|
||||||
|
m_command = command_util::make_command(exec);
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_command->exec(false);
|
||||||
|
} catch (const exception& err) {
|
||||||
|
m_log.err("%s: %s", name(), err.what());
|
||||||
|
throw module_error("Failed to execute command, stopping module...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (io_util::poll(m_command->get_stdout(PIPE_READ), POLLIN, 0)) {
|
||||||
|
if ((m_output = m_command->readline()) != m_prev) {
|
||||||
|
m_prev = m_output;
|
||||||
|
broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
guard.unlock();
|
||||||
|
|
||||||
|
if (m_command && !m_command->is_running()) {
|
||||||
|
sleep(std::max(m_command->get_exit_status() == 0 ? m_interval : 1s, m_interval));
|
||||||
|
} else {
|
||||||
|
sleep(m_interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
POLYBAR_NS_END
|
@ -51,18 +51,22 @@ file_descriptor::file_descriptor(const string& path, int flags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file_descriptor::file_descriptor(int fd) : m_fd(fd) {
|
file_descriptor::file_descriptor(int fd, bool autoclose) : m_fd(fd), m_autoclose(autoclose) {
|
||||||
if (m_fd != -1 && !*this) {
|
if (m_fd != -1 && !*this) {
|
||||||
throw system_error("Given file descriptor (" + to_string(m_fd) + ") is not valid");
|
throw system_error("Given file descriptor (" + to_string(m_fd) + ") is not valid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file_descriptor::~file_descriptor() {
|
file_descriptor::~file_descriptor() {
|
||||||
close();
|
if (m_autoclose) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file_descriptor& file_descriptor::operator=(const int fd) {
|
file_descriptor& file_descriptor::operator=(const int fd) {
|
||||||
close();
|
if (m_autoclose) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
m_fd = fd;
|
m_fd = fd;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -96,10 +100,6 @@ void file_descriptor::close() {
|
|||||||
// }}}
|
// }}}
|
||||||
// implementation of file_streambuf {{{
|
// implementation of file_streambuf {{{
|
||||||
|
|
||||||
fd_streambuf::fd_streambuf(int fd) : m_fd(-1) {
|
|
||||||
open(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
fd_streambuf::~fd_streambuf() {
|
fd_streambuf::~fd_streambuf() {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
@ -186,9 +186,10 @@ namespace file_util {
|
|||||||
*/
|
*/
|
||||||
string contents(const string& filename) {
|
string contents(const string& filename) {
|
||||||
try {
|
try {
|
||||||
std::ifstream ifs(filename);
|
string contents;
|
||||||
return string((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
std::getline(std::ifstream(filename, std::ifstream::in), contents);
|
||||||
} catch (std::ios_base::failure& e) {
|
return contents;
|
||||||
|
} catch (const std::ifstream::failure& e) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -196,12 +197,9 @@ namespace file_util {
|
|||||||
/**
|
/**
|
||||||
* Checks if the given file is a named pipe
|
* Checks if the given file is a named pipe
|
||||||
*/
|
*/
|
||||||
bool is_fifo(string filename) {
|
bool is_fifo(const string& filename) {
|
||||||
auto fileptr = factory_util::unique<file_ptr>(filename);
|
struct stat buffer {};
|
||||||
int fd = fileno(*fileptr);
|
return stat(filename.c_str(), &buffer) == 0 && S_ISFIFO(buffer.st_mode);
|
||||||
struct stat statbuf {};
|
|
||||||
fstat(fd, &statbuf);
|
|
||||||
return S_ISFIFO(statbuf.st_mode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,91 +3,52 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
#include "errors.hpp"
|
#include "errors.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
#include "utils/io.hpp"
|
#include "utils/io.hpp"
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
namespace io_util {
|
namespace io_util {
|
||||||
string read(int read_fd, int bytes_to_read, int& bytes_read_loc, int& status_loc) {
|
string read(int read_fd, size_t bytes_to_read) {
|
||||||
char buffer[BUFSIZ - 1];
|
fd_stream<std::istream> in(read_fd, false);
|
||||||
|
char buffer[BUFSIZ];
|
||||||
if (bytes_to_read == -1) {
|
in.getline(buffer, bytes_to_read);
|
||||||
bytes_to_read = sizeof(buffer);
|
string out{buffer};
|
||||||
}
|
return out;
|
||||||
|
|
||||||
status_loc = 0;
|
|
||||||
|
|
||||||
if ((bytes_read_loc = ::read(read_fd, &buffer, bytes_to_read)) == -1) {
|
|
||||||
throw system_error("Error trying to read from fd");
|
|
||||||
} else if (bytes_read_loc == 0) {
|
|
||||||
status_loc = -1;
|
|
||||||
} else {
|
|
||||||
buffer[bytes_read_loc] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return {buffer};
|
|
||||||
}
|
|
||||||
|
|
||||||
string read(int read_fd, int bytes_to_read) {
|
|
||||||
int bytes_read = 0;
|
|
||||||
int status = 0;
|
|
||||||
return read(read_fd, bytes_to_read, bytes_read, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
string readline(int read_fd, int& bytes_read) {
|
|
||||||
stringstream buffer;
|
|
||||||
char char_;
|
|
||||||
int bytes = 0;
|
|
||||||
bytes_read = 0;
|
|
||||||
|
|
||||||
while ((bytes = ::read(read_fd, &char_, 1)) > 0) {
|
|
||||||
if (bytes <= 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (char_ == '\n' || char_ == '\x00') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bytes_read += bytes;
|
|
||||||
buffer << char_;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes_read <= 0) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return string_util::strip_trailing_newline(buffer.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string readline(int read_fd) {
|
string readline(int read_fd) {
|
||||||
int bytes_read;
|
fd_stream<std::istream> in(read_fd, false);
|
||||||
return readline(read_fd, bytes_read);
|
string out;
|
||||||
|
std::getline(in, out);
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t write(int write_fd, const string& data) {
|
size_t write(int write_fd, size_t bytes_to_write, const string& data) {
|
||||||
return ::write(write_fd, data.c_str(), strlen(data.c_str()));
|
fd_stream<std::ostream> out(write_fd, false);
|
||||||
|
out.write(data.c_str(), bytes_to_write).flush();
|
||||||
|
return out.good() ? data.size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t writeline(int write_fd, const string& data) {
|
size_t writeline(int write_fd, const string& data) {
|
||||||
if (data.length() == 0) {
|
fd_stream<std::ostream> out(write_fd, false);
|
||||||
return -1;
|
if (data[data.size() - 1] != '\n') {
|
||||||
}
|
out << data << std::endl;
|
||||||
if (data.substr(data.length() - 1, 1) != "\n") {
|
|
||||||
return io_util::write(write_fd, data + "\n");
|
|
||||||
} else {
|
} else {
|
||||||
return io_util::write(write_fd, data);
|
out << data << std::flush;
|
||||||
}
|
}
|
||||||
|
return out.good() ? data.size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tail(int read_fd, const function<void(string)>& callback) {
|
void tail(int read_fd, const function<void(string)>& callback) {
|
||||||
int bytes_read;
|
string line;
|
||||||
while (true) {
|
fd_stream<std::istream> in(read_fd, false);
|
||||||
auto line = io_util::readline(read_fd, bytes_read);
|
while (std::getline(in, line)) {
|
||||||
if (bytes_read <= 0) {
|
callback(move(line));
|
||||||
break;
|
|
||||||
}
|
|
||||||
callback(line);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,9 +60,7 @@ namespace io_util {
|
|||||||
struct pollfd fds[1];
|
struct pollfd fds[1];
|
||||||
fds[0].fd = fd;
|
fds[0].fd = fd;
|
||||||
fds[0].events = events;
|
fds[0].events = events;
|
||||||
|
|
||||||
::poll(fds, 1, timeout_ms);
|
::poll(fds, 1, timeout_ms);
|
||||||
|
|
||||||
return fds[0].revents & events;
|
return fds[0].revents & events;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,9 +73,7 @@ namespace io_util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool interrupt_read(int write_fd) {
|
bool interrupt_read(int write_fd) {
|
||||||
char end[1] = {'\n'};
|
return writeline(write_fd, "") > 0;
|
||||||
size_t bytes = ::write(write_fd, end, 1);
|
|
||||||
return bytes > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_block(int fd) {
|
void set_block(int fd) {
|
||||||
|
Loading…
Reference in New Issue
Block a user