fix(formatting): Make formats parse specs as-is

This removes the spacing tinkering when parsing format specs.
The following example uses the old behavoir:

    format-test = <label-foo>  <label-bar>
    format-breaks = <label-foo><label-bar>/<bar-test>

`format-test` would replace all occurences of ' ' with the
a space string with defined `spacing` as its width. `format-breaks` would
not validate as the tags where split with ' ' as delimiter.

All that nonsense has been removed and each tag is extracted as is.
The `spacing` parameter can still be used to apply N extra whitespaces
between the tags, but it is now 0 by default.
This commit is contained in:
Michael Carlberg 2017-01-11 01:42:55 +01:00
parent f4e8051e9e
commit 30f516dd7d
9 changed files with 90 additions and 69 deletions

View File

@ -39,7 +39,6 @@ underline-color = #00f
border-bottom = 2 border-bottom = 2
border-bottom-color = #333 border-bottom-color = #333
spacing = 1
padding-left = 0 padding-left = 0
padding-right = 2 padding-right = 2
module-margin-left = 1 module-margin-left = 1
@ -77,14 +76,10 @@ label = %title:0:30:...%
[module/xkeyboard] [module/xkeyboard]
type = internal/xkeyboard type = internal/xkeyboard
blacklist-0 = num lock blacklist-0 = num lock
label-layout = %{F#55}%{F-} %layout%
format-underline = ${colors.secondary} label-layout-underline = ${colors.secondary}
format-prefix = " "
format-prefix-foreground = ${colors.foreground-alt}
label-layout = %layout%
label-indicator-padding = 2 label-indicator-padding = 2
label-indicator-margin = 1
label-indicator-background = ${colors.secondary} label-indicator-background = ${colors.secondary}
label-indicator-underline = ${colors.secondary} label-indicator-underline = ${colors.secondary}
@ -331,6 +326,8 @@ ramp-foreground = ${colors.foreground-alt}
[module/powermenu] [module/powermenu]
type = custom/menu type = custom/menu
format-spacing = 1
label-open = power label-open = power
label-open-foreground = ${colors.secondary} label-open-foreground = ${colors.secondary}
label-close = cancel label-close = cancel

View File

@ -143,7 +143,7 @@ struct bar_settings {
std::unordered_map<edge, border_settings, enum_hash> borders{}; std::unordered_map<edge, border_settings, enum_hash> borders{};
uint8_t spacing{1U}; uint8_t spacing{0};
string separator{}; string separator{};
string wmname{}; string wmname{};

View File

@ -68,10 +68,12 @@ namespace modules {
string bg{}; string bg{};
string ul{}; string ul{};
string ol{}; string ol{};
int spacing{}; size_t ulsize{0};
int padding{}; size_t olsize{0};
int margin{}; size_t spacing{0};
int offset{}; size_t padding{0};
size_t margin{0};
int offset{0};
string decorate(builder* builder, string output); string decorate(builder* builder, string output);
}; };

View File

@ -1,6 +1,6 @@
#include "components/builder.hpp" #include "components/builder.hpp"
#include "components/logger.hpp"
#include "components/config.hpp" #include "components/config.hpp"
#include "components/logger.hpp"
#include "events/signal.hpp" #include "events/signal.hpp"
#include "events/signal_emitter.hpp" #include "events/signal_emitter.hpp"
@ -123,24 +123,34 @@ namespace modules {
auto format_name = CONST_MOD(Impl).get_format(); auto format_name = CONST_MOD(Impl).get_format();
auto format = m_formatter->get(format_name); auto format = m_formatter->get(format_name);
int i = 0; int i{0};
bool tag_built = true; bool prevtag{true};
for (auto&& tag : string_util::split(format->value, ' ')) { auto mingap = std::max(1UL, format->spacing);
bool is_blankspace = tag.empty();
if (tag[0] == '<' && tag[tag.length() - 1] == '>') { size_t start, end;
string value{format->value};
while ((start = value.find('<')) != string::npos && (end = value.find('>', start)) != string::npos) {
if (start > 0) {
m_builder->node(value.substr(0, start));
value.erase(0, start);
end -= start;
start = 0;
}
string tag{value.substr(start, end + 1)};
if (tag[0] == '<' && tag[tag.size() - 1] == '>') {
if (i > 0) if (i > 0)
m_builder->space(format->spacing); m_builder->space(format->spacing);
if (!(tag_built = CONST_MOD(Impl).build(m_builder.get(), tag)) && i > 0) if (!(prevtag = CONST_MOD(Impl).build(m_builder.get(), tag)) && i > 0)
m_builder->remove_trailing_space(format->spacing); m_builder->remove_trailing_space(mingap);
if (tag_built) if (prevtag)
i++; i++;
} else if (is_blankspace && tag_built) {
m_builder->space(1_z);
} else if (!is_blankspace) {
m_builder->node(tag);
} }
value.erase(0, tag.size());
}
if (!value.empty()) {
m_builder->append(value);
} }
return format->decorate(&*m_builder, m_builder->flush()); return format->decorate(&*m_builder, m_builder->flush());

View File

@ -301,7 +301,11 @@ void builder::offset(int pixels) {
* Insert spaces * Insert spaces
*/ */
void builder::space(size_t width) { void builder::space(size_t width) {
if (width) {
m_output.append(width, ' '); m_output.append(width, ' ');
} else {
space();
}
} }
void builder::space() { void builder::space() {
m_output.append(m_bar.spacing, ' '); m_output.append(m_bar.spacing, ' ');

View File

@ -1,20 +1,16 @@
#include <algorithm> #include <climits>
#include <chrono>
#include <fstream> #include <fstream>
#include <istream>
#include <utility>
#include "components/config.hpp" #include "components/config.hpp"
#include "utils/env.hpp" #include "utils/env.hpp"
#include "utils/factory.hpp" #include "utils/factory.hpp"
#include "utils/file.hpp" #include "utils/file.hpp"
#include "utils/math.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
#include "x11/color.hpp" #include "x11/color.hpp"
POLYBAR_NS POLYBAR_NS
namespace chrono = std::chrono;
/** /**
* Create instance * Create instance
*/ */
@ -33,6 +29,7 @@ config::config(const logger& logger, string&& path, string&& bar)
} }
parse_file(); parse_file();
copy_inherited();
bool found_bar{false}; bool found_bar{false};
for (auto&& p : m_sections) { for (auto&& p : m_sections) {
@ -127,8 +124,6 @@ void config::parse_file() {
m_sections[section].emplace_hint(it, move(key), move(value)); m_sections[section].emplace_hint(it, move(key), move(value));
} }
copy_inherited();
} }
/** /**
@ -246,12 +241,14 @@ unsigned int config::convert(string&& value) const {
template <> template <>
unsigned long config::convert(string&& value) const { unsigned long config::convert(string&& value) const {
return std::strtoul(value.c_str(), nullptr, 10); unsigned long v{std::strtoul(value.c_str(), nullptr, 10)};
return v < ULONG_MAX ? v : 0UL;
} }
template <> template <>
unsigned long long config::convert(string&& value) const { unsigned long long config::convert(string&& value) const {
return std::strtoull(value.c_str(), nullptr, 10); unsigned long v{std::strtoull(value.c_str(), nullptr, 10)};
return v < ULLONG_MAX ? v : 0ULL;
} }
template <> template <>

View File

@ -12,7 +12,9 @@ namespace modules {
template class module<menu_module>; template class module<menu_module>;
menu_module::menu_module(const bar_settings& bar, string name_) : static_module<menu_module>(bar, move(name_)) { menu_module::menu_module(const bar_settings& bar, string name_) : static_module<menu_module>(bar, move(name_)) {
string default_format{TAG_LABEL_TOGGLE + string{" "} + TAG_MENU}; string default_format;
default_format += TAG_LABEL_TOGGLE;
default_format += TAG_MENU;
m_formatter->add(DEFAULT_FORMAT, default_format, {TAG_LABEL_TOGGLE, TAG_MENU}); m_formatter->add(DEFAULT_FORMAT, default_format, {TAG_LABEL_TOGGLE, TAG_MENU});
@ -63,12 +65,14 @@ namespace modules {
builder->node(m_labelclose); builder->node(m_labelclose);
builder->cmd_close(); builder->cmd_close();
} else if (tag == TAG_MENU && m_level > -1) { } else if (tag == TAG_MENU && m_level > -1) {
auto spacing = m_formatter->get(get_format())->spacing;
for (auto&& item : m_levels[m_level]->items) { for (auto&& item : m_levels[m_level]->items) {
if (item != m_levels[m_level]->items.front()) {
builder->space();
}
if (*m_labelseparator) { if (*m_labelseparator) {
builder->node(m_labelseparator, true); if (item != m_levels[m_level]->items[0]) {
builder->space(spacing);
}
builder->node(m_labelseparator);
builder->space(spacing);
} }
builder->cmd(mousebtn::LEFT, item->exec); builder->cmd(mousebtn::LEFT, item->exec);
builder->node(item->label); builder->node(item->label);

View File

@ -69,19 +69,18 @@ namespace modules {
// module_formatter {{{ // module_formatter {{{
void module_formatter::add(string name, string fallback, vector<string>&& tags, vector<string>&& whitelist) { void module_formatter::add(string name, string fallback, vector<string>&& tags, vector<string>&& whitelist) {
using namespace std::string_literals;
auto format = make_unique<module_format>(); auto format = make_unique<module_format>();
format->value = m_conf.get(m_modname, name, move(fallback)); format->value = m_conf.get(m_modname, name, move(fallback));
format->fg = m_conf.get(m_modname, name + "-foreground", ""s); format->fg = m_conf.get(m_modname, name + "-foreground", format->fg);
format->bg = m_conf.get(m_modname, name + "-background", ""s); format->bg = m_conf.get(m_modname, name + "-background", format->bg);
format->ul = m_conf.get(m_modname, name + "-underline", ""s); format->ul = m_conf.get(m_modname, name + "-underline", format->ul);
format->ol = m_conf.get(m_modname, name + "-overline", ""s); format->ol = m_conf.get(m_modname, name + "-overline", format->ol);
format->spacing = m_conf.get(m_modname, name + "-spacing", 1_z); format->ulsize = m_conf.get(m_modname, name + "-underline-size", format->ulsize);
format->padding = m_conf.get(m_modname, name + "-padding", 0_z); format->olsize = m_conf.get(m_modname, name + "-overline-size", format->olsize);
format->margin = m_conf.get(m_modname, name + "-margin", 0_z); format->spacing = m_conf.get(m_modname, name + "-spacing", format->spacing);
format->offset = m_conf.get(m_modname, name + "-offset", 0_z); format->padding = m_conf.get(m_modname, name + "-padding", format->padding);
format->margin = m_conf.get(m_modname, name + "-margin", format->margin);
format->offset = m_conf.get(m_modname, name + "-offset", format->offset);
format->tags.swap(tags); format->tags.swap(tags);
try { try {
@ -96,16 +95,24 @@ namespace modules {
// suffix not defined // suffix not defined
} }
for (auto&& tag : string_util::split(format->value, ' ')) { vector<string> tag_collection;
if (tag[0] != '<' || tag[tag.length() - 1] != '>') { tag_collection.reserve(format->tags.size() + whitelist.size());
continue; tag_collection.insert(tag_collection.end(), format->tags.begin(), format->tags.end());
} else if (find(format->tags.begin(), format->tags.end(), tag) != format->tags.end()) { tag_collection.insert(tag_collection.end(), whitelist.begin(), whitelist.end());
continue;
} else if (find(whitelist.begin(), whitelist.end(), tag) != whitelist.end()) { size_t start, end;
continue; string value{format->value};
} else { while ((start = value.find('<')) != string::npos && (end = value.find('>', start)) != string::npos) {
if (start > 0) {
value.erase(0, start);
end -= start;
start = 0;
}
string tag{value.substr(start, end + 1)};
if (find(tag_collection.begin(), tag_collection.end(), tag) == tag_collection.end()) {
throw undefined_format_tag(tag + " is not a valid format tag for \"" + name + "\""); throw undefined_format_tag(tag + " is not a valid format tag for \"" + name + "\"");
} }
value.erase(0, tag.size());
} }
m_formats.insert(make_pair(move(name), move(format))); m_formats.insert(make_pair(move(name), move(format)));

View File

@ -100,7 +100,7 @@ namespace modules {
bool xkeyboard_module::build(builder* builder, const string& tag) const { bool xkeyboard_module::build(builder* builder, const string& tag) const {
if (tag == TAG_LABEL_LAYOUT) { if (tag == TAG_LABEL_LAYOUT) {
builder->node(m_layout); builder->node(m_layout);
} else if (tag == TAG_LABEL_INDICATOR) { } else if (tag == TAG_LABEL_INDICATOR && !m_indicators.empty()) {
size_t n{0}; size_t n{0};
for (auto&& indicator : m_indicators) { for (auto&& indicator : m_indicators) {
if (n++) { if (n++) {