feat(script): add formatting for script failure (#2596)

Closes #2588

* feat(script): add formatting for script failure

* refactor: address review comments

* doc: add changelog entry

* refactor: minor cleanup
This commit is contained in:
Maxim Kolesnikov 2022-02-23 21:01:28 +07:00 committed by GitHub
parent dc46251571
commit f5bfbccfc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 8 deletions

View File

@ -81,6 +81,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `DEBUG_SHADED` cmake variable and its associated functionality. - `DEBUG_SHADED` cmake variable and its associated functionality.
### Added ### Added
- `custom/script`: Add formatting for script failure (`format-fail`, `label-fail`) ([`#2588`](https://github.com/polybar/polybar/issues/2588))
- Support `px` and `pt` units everyhwere where before only a number of spaces - Support `px` and `pt` units everyhwere where before only a number of spaces
or pixels could be specified. or pixels could be specified.
([`#2578`](https://github.com/polybar/polybar/pull/2578)) ([`#2578`](https://github.com/polybar/polybar/pull/2578))

View File

@ -24,13 +24,14 @@ class script_runner {
int get_pid() const; int get_pid() const;
int get_counter() const; int get_counter() const;
int get_exit_status() const;
string get_output(); string get_output();
bool is_stopping() const; bool is_stopping() const;
protected: protected:
bool set_output(const string&&); bool set_output(string&&);
interval run_tail(); interval run_tail();
interval run(); interval run();
@ -52,6 +53,7 @@ class script_runner {
std::atomic_int m_counter{0}; std::atomic_int m_counter{0};
std::atomic_bool m_stopping{false}; std::atomic_bool m_stopping{false};
std::atomic_int m_pid{-1}; std::atomic_int m_pid{-1};
std::atomic_int m_exit_status{0};
}; };
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -16,6 +16,8 @@ namespace modules {
void stop() override; void stop() override;
string get_output(); string get_output();
string get_format() const;
bool build(builder* builder, const string& tag) const; bool build(builder* builder, const string& tag) const;
static constexpr auto TYPE = "custom/script"; static constexpr auto TYPE = "custom/script";
@ -24,7 +26,9 @@ namespace modules {
bool check_condition(); bool check_condition();
private: private:
static constexpr const char* TAG_LABEL{"<label>"}; static constexpr auto TAG_LABEL = "<label>";
static constexpr auto TAG_LABEL_FAIL = "<label-fail>";
static constexpr auto FORMAT_FAIL = "format-fail";
const bool m_tail; const bool m_tail;
const script_runner::interval m_interval{0}; const script_runner::interval m_interval{0};
@ -34,6 +38,7 @@ namespace modules {
map<mousebtn, string> m_actions; map<mousebtn, string> m_actions;
label_t m_label; label_t m_label;
label_t m_label_fail;
}; };
} // namespace modules } // namespace modules

View File

@ -60,6 +60,10 @@ int script_runner::get_counter() const {
return m_counter; return m_counter;
} }
int script_runner::get_exit_status() const {
return m_exit_status;
}
string script_runner::get_output() { string script_runner::get_output() {
std::lock_guard<std::mutex> guard(m_output_lock); std::lock_guard<std::mutex> guard(m_output_lock);
return m_output; return m_output;
@ -74,7 +78,7 @@ bool script_runner::is_stopping() const {
* *
* Returns true if the output changed. * Returns true if the output changed.
*/ */
bool script_runner::set_output(const string&& new_output) { bool script_runner::set_output(string&& new_output) {
std::lock_guard<std::mutex> guard(m_output_lock); std::lock_guard<std::mutex> guard(m_output_lock);
if (m_output != new_output) { if (m_output != new_output) {
@ -98,16 +102,16 @@ script_runner::interval script_runner::run() {
throw modules::module_error("Failed to execute command, stopping module..."); throw modules::module_error("Failed to execute command, stopping module...");
} }
int status = cmd->get_exit_status(); m_exit_status = cmd->get_exit_status();
int fd = cmd->get_stdout(PIPE_READ); int fd = cmd->get_stdout(PIPE_READ);
assert(fd != -1); assert(fd != -1);
bool changed = io_util::poll_read(fd) && set_output(cmd->readline()); bool changed = io_util::poll_read(fd) && set_output(cmd->readline());
if (!changed && status != 0) { if (!changed && m_exit_status != 0) {
clear_output(); clear_output();
} }
if (status == 0) { if (m_exit_status == 0) {
return m_interval; return m_interval;
} else { } else {
return std::max(m_interval, interval{1s}); return std::max(m_interval, interval{1s});
@ -142,7 +146,7 @@ script_runner::interval script_runner::run_tail() {
return 0s; return 0s;
} }
bool exit_status = cmd->wait(); auto exit_status = cmd->wait();
if (exit_status == 0) { if (exit_status == 0) {
return m_interval; return m_interval;

View File

@ -25,7 +25,12 @@ namespace modules {
// Setup formatting // Setup formatting
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL}); m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL});
if (m_formatter->has(TAG_LABEL)) { if (m_formatter->has(TAG_LABEL)) {
m_label = load_optional_label(m_conf, name(), "label", "%output%"); m_label = load_optional_label(m_conf, name(), TAG_LABEL, "%output%");
}
m_formatter->add_optional(FORMAT_FAIL, {TAG_LABEL_FAIL});
if (m_formatter->has(TAG_LABEL_FAIL)) {
m_label_fail = load_optional_label(m_conf, name(), TAG_LABEL_FAIL, "%output%");
} }
} }
@ -70,6 +75,13 @@ namespace modules {
/** /**
* Generate module output * Generate module output
*/ */
string script_module::get_format() const {
if (m_runner.get_exit_status() != 0 && m_conf.has(name(), FORMAT_FAIL)) {
return FORMAT_FAIL;
}
return DEFAULT_FORMAT;
}
string script_module::get_output() { string script_module::get_output() {
auto script_output = m_runner.get_output(); auto script_output = m_runner.get_output();
if (script_output.empty()) { if (script_output.empty()) {
@ -81,6 +93,11 @@ namespace modules {
m_label->replace_token("%output%", script_output); m_label->replace_token("%output%", script_output);
} }
if (m_label_fail) {
m_label_fail->reset_tokens();
m_label_fail->replace_token("%output%", script_output);
}
string cnt{to_string(m_runner.get_counter())}; string cnt{to_string(m_runner.get_counter())};
string output{module::get_output()}; string output{module::get_output()};
@ -114,6 +131,8 @@ namespace modules {
bool script_module::build(builder* builder, const string& tag) const { bool script_module::build(builder* builder, const string& tag) const {
if (tag == TAG_LABEL) { if (tag == TAG_LABEL) {
builder->node(m_label); builder->node(m_label);
} else if (tag == TAG_LABEL_FAIL) {
builder->node(m_label_fail);
} else { } else {
return false; return false;
} }