2020-12-17 19:37:28 +00:00
|
|
|
#include "tags/parser.hpp"
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
#include <cctype>
|
|
|
|
|
Add units support (POINT, PIXEL, SPACE) (#2578)
* add units support (POINT, PIXEL, SPACE) for polybar
- add a size_with_unit struct
- add a geometry_format_values struct
- move dpi initialisation from renderer.cpp to bar.cpp
- add a string to size_with_unit converter
- add point support (with pt)
- add pixel support (with px)
* Fix unit test compilation
* clang-format
* Better names
The old names didn't really capture the purpose of the structs and
function.
space_type -> spacing_type
space_size -> spacing_val
size_type -> extent_type
geometry -> extent_val
geometry_format_values -> percentage_with_offset
* Remove parse_size_with_unit
No longer needed. The convert<spacing_val> function in config.cpp
already does all the work for us and always setting the type to pixel
was wrong.
In addition, line-size should not be of type spacing_val but extent_val.
* Cleanup
I tried to address most of my comments on the old PR
* Fix renderer width calculation
We can't just blindly add the x difference to the width because for
example the width should increase if x < width and the increase keeps
x < width.
Similarly, we can't just add the offset to the width.
* Rename geom_format_to_pixels to percentage_with_offset_to_pixel
* Cleanup
* Apply suggested changes from Patrick on GitHub
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/bar.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/config.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/builder.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/builder.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* config: Use stod for parsing percentage
* Use stof instead of strtof
* units: Fix test edge cases
* Remove unnecessary clang-format toggle
* Use percentage_with_offset for margin-{top,bottom}
* Support negative extent values
* Rename unit to units and create a cpp file
* Move percentage_with_offset_to_pixel unit test to units
* Add unit tests for units_utils
* Clarify when and how negative spacing/extent is allowed
Negative spacing is never allowed and produces a config error.
Extents allow negative values in theory, but only a few use-cases accept
it.
Only the extent value used for the `%{O}` tag and the offset value in
percentage_with_offset can be negative. Everything else is capped below
at 0.
The final pixel value of percentage_with_offset also caps below at 0.
* Fix parsing errors not being caught in config
* Print a proper error message for uncaught exceptions
* Cleanup module::get_output
All changes preserve the existing semantics
* Stop using remove_trailing_space in module::get_output
Instead, we first check if the current tag is built, and only if it is,
the spacing is prepended.
* Remove unused imports
* Restore old behavior
If there are two tags and the second one isn't built (module::build
returns false), the space in between them is removed.
For example in the mpd module:
format-online = <toggle> <label-song> foo
If mpd is not running, the mpd module will return false when trying to
build the `<label-song>` tag. If we don't remove the space between
`<toggle>` and `<label-song>`, we end up with two spaces between
`<toggle>` and `foo`.
This change is to match the old behavior where at least one trailing
space character was removed from the builder.
* Add changelog entry
* Remove unused setting
* Use percentage with offset for tray-offset
Co-authored-by: Jérôme BOULMIER <jerome.boulmier@outlook.fr>
Co-authored-by: Joe Groocock <github@frebib.net>
2022-02-20 20:08:57 +00:00
|
|
|
#include "utils/units.hpp"
|
|
|
|
|
2020-12-17 19:37:28 +00:00
|
|
|
POLYBAR_NS
|
|
|
|
|
|
|
|
namespace tags {
|
|
|
|
|
|
|
|
bool parser::has_next_element() {
|
|
|
|
return buf_pos < buf.size() || has_next();
|
|
|
|
}
|
|
|
|
|
|
|
|
element parser::next_element() {
|
|
|
|
if (!has_next_element()) {
|
|
|
|
throw std::runtime_error("tag parser: No next element");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buf_pos >= buf.size()) {
|
|
|
|
parse_step();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buf_pos >= buf.size()) {
|
|
|
|
throw std::runtime_error("tag parser: No next element. THIS IS A BUG. (Context: '" + input + "')");
|
|
|
|
}
|
|
|
|
|
|
|
|
element e = buf[buf_pos];
|
|
|
|
buf_pos++;
|
|
|
|
|
|
|
|
if (buf_pos == buf.size()) {
|
|
|
|
buf.clear();
|
|
|
|
buf_pos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
format_string parser::parse() {
|
|
|
|
format_string parsed;
|
|
|
|
|
|
|
|
while (has_next_element()) {
|
|
|
|
parsed.push_back(next_element());
|
|
|
|
}
|
|
|
|
|
|
|
|
return parsed;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Performs a single parse step.
|
|
|
|
*
|
|
|
|
* This means it will parse text until the next tag is reached or it will
|
|
|
|
* parse an entire %{...} tag.
|
|
|
|
*/
|
|
|
|
void parser::parse_step() {
|
|
|
|
char c;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we have already parsed text, we can stop if we reach a tag.
|
|
|
|
*/
|
|
|
|
bool text_parsed = false;
|
|
|
|
|
|
|
|
size_t start_pos = pos;
|
|
|
|
|
|
|
|
try {
|
|
|
|
while ((c = next())) {
|
|
|
|
// TODO here we could think about how to escape an action tag
|
|
|
|
if (c == '%' && has_next() && peek() == '{') {
|
|
|
|
/*
|
|
|
|
* If we have already parsed text, encountering a tag opening means
|
|
|
|
* we can stop parsing now because we parsed at least one entire
|
|
|
|
* element (the text up to the beginning of the tag).
|
|
|
|
*/
|
|
|
|
if (text_parsed) {
|
|
|
|
// Put back the '%'
|
|
|
|
revert();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
consume('{');
|
|
|
|
consume_space();
|
|
|
|
parse_tag();
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
push_char(c);
|
|
|
|
text_parsed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (error& e) {
|
|
|
|
e.set_context(input.substr(start_pos, pos - start_pos));
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void parser::set(const string&& input) {
|
|
|
|
this->input = std::move(input);
|
|
|
|
pos = 0;
|
|
|
|
buf.clear();
|
|
|
|
buf_pos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool parser::has_next() const {
|
|
|
|
return pos < input.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
char parser::next() {
|
|
|
|
char c = peek();
|
|
|
|
pos++;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
char parser::peek() const {
|
|
|
|
if (!has_next()) {
|
|
|
|
return EOL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return input[pos];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Puts back a single character in the input string.
|
|
|
|
*/
|
|
|
|
void parser::revert() {
|
|
|
|
assert(pos > 0);
|
|
|
|
pos--;
|
|
|
|
}
|
|
|
|
|
|
|
|
void parser::consume(char c) {
|
|
|
|
char n = next();
|
|
|
|
if (n != c) {
|
|
|
|
throw tags::token_error(n, c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void parser::consume_space() {
|
|
|
|
while (peek() == ' ') {
|
|
|
|
next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parses an entire %{....} tag.
|
|
|
|
*
|
|
|
|
* '%' and '{' were already consumed and we are currently on the first character
|
|
|
|
* inside the tag.
|
|
|
|
* At the end of this method, we should be on the closing '}' character (not
|
|
|
|
* yet consumed).
|
|
|
|
*/
|
|
|
|
|
|
|
|
void parser::parse_tag() {
|
|
|
|
if (!has_next()) {
|
|
|
|
throw token_error(EOL, "Formatting tag content");
|
|
|
|
}
|
|
|
|
|
|
|
|
while (has_next()) {
|
|
|
|
parse_single_tag_content();
|
|
|
|
|
|
|
|
int p = peek();
|
|
|
|
|
|
|
|
if (p != ' ' && p != '}') {
|
|
|
|
throw tag_end_error(p);
|
|
|
|
} else {
|
|
|
|
/**
|
|
|
|
* Consume whitespace between elements inside the tag
|
|
|
|
*/
|
|
|
|
consume_space();
|
|
|
|
|
|
|
|
if (peek() == '}') {
|
|
|
|
consume('}');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parses a single element inside a formatting tag.
|
|
|
|
*
|
|
|
|
* For example it would parse the foreground part of the following tag:
|
|
|
|
*
|
|
|
|
* %{F#ff0000 B#ff0000}
|
|
|
|
* ^ ^
|
|
|
|
* | - Pointer at the end
|
|
|
|
* |
|
|
|
|
* - Pointer at the start
|
|
|
|
*/
|
|
|
|
void parser::parse_single_tag_content() {
|
|
|
|
char c = next();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* %{U...} is a special case because it produces over and underline tags.
|
|
|
|
*/
|
|
|
|
if (c == 'U') {
|
|
|
|
element e{};
|
|
|
|
e.is_tag = true;
|
|
|
|
e.tag_data.type = tag_type::FORMAT;
|
|
|
|
e.tag_data.subtype.format = syntaxtag::u;
|
|
|
|
e.tag_data.color = parse_color();
|
|
|
|
buf.emplace_back(e);
|
|
|
|
|
|
|
|
e.tag_data.subtype.format = syntaxtag::o;
|
|
|
|
buf.emplace_back(e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
tag_type type;
|
|
|
|
tag_subtype sub;
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
// clang-format off
|
|
|
|
case 'B': sub.format = syntaxtag::B; break;
|
|
|
|
case 'F': sub.format = syntaxtag::F; break;
|
|
|
|
case 'u': sub.format = syntaxtag::u; break;
|
|
|
|
case 'o': sub.format = syntaxtag::o; break;
|
|
|
|
case 'T': sub.format = syntaxtag::T; break;
|
|
|
|
case 'R': sub.format = syntaxtag::R; break;
|
|
|
|
case 'O': sub.format = syntaxtag::O; break;
|
|
|
|
case 'P': sub.format = syntaxtag::P; break;
|
|
|
|
case 'A': sub.format = syntaxtag::A; break;
|
|
|
|
case 'l': sub.format = syntaxtag::l; break;
|
|
|
|
case 'c': sub.format = syntaxtag::c; break;
|
|
|
|
case 'r': sub.format = syntaxtag::r; break;
|
|
|
|
|
|
|
|
case '+': sub.activation = attr_activation::ON; break;
|
|
|
|
case '-': sub.activation = attr_activation::OFF; break;
|
|
|
|
case '!': sub.activation = attr_activation::TOGGLE; break;
|
|
|
|
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw unrecognized_tag(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
case 'B':
|
|
|
|
case 'F':
|
|
|
|
case 'u':
|
|
|
|
case 'o':
|
|
|
|
case 'T':
|
|
|
|
case 'R':
|
|
|
|
case 'O':
|
|
|
|
case 'P':
|
|
|
|
case 'A':
|
|
|
|
case 'l':
|
|
|
|
case 'c':
|
|
|
|
case 'r':
|
|
|
|
type = tag_type::FORMAT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '+':
|
|
|
|
case '-':
|
|
|
|
case '!':
|
|
|
|
type = tag_type::ATTR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw unrecognized_tag(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
tag tag_data{};
|
|
|
|
tag_data.type = type;
|
|
|
|
tag_data.subtype = sub;
|
|
|
|
|
|
|
|
element e{};
|
|
|
|
e.is_tag = true;
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
case 'B':
|
|
|
|
case 'F':
|
|
|
|
case 'u':
|
|
|
|
case 'o':
|
|
|
|
tag_data.color = parse_color();
|
|
|
|
break;
|
|
|
|
case 'T':
|
|
|
|
tag_data.font = parse_fontindex();
|
|
|
|
break;
|
|
|
|
case 'O':
|
|
|
|
tag_data.offset = parse_offset();
|
|
|
|
break;
|
|
|
|
case 'P':
|
|
|
|
tag_data.ctrl = parse_control();
|
|
|
|
break;
|
|
|
|
case 'A':
|
|
|
|
std::tie(tag_data.action, e.data) = parse_action();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '+':
|
|
|
|
case '-':
|
|
|
|
case '!':
|
|
|
|
tag_data.attr = parse_attribute();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
e.tag_data = tag_data;
|
|
|
|
buf.emplace_back(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
color_value parser::parse_color() {
|
|
|
|
string s = get_tag_value();
|
|
|
|
|
|
|
|
color_value ret;
|
|
|
|
|
|
|
|
if (s.empty() || s == "-") {
|
|
|
|
ret.type = color_type::RESET;
|
|
|
|
} else {
|
|
|
|
rgba c{s};
|
|
|
|
|
|
|
|
if (!c.has_color()) {
|
|
|
|
throw color_error(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret.type = color_type::COLOR;
|
|
|
|
ret.val = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int parser::parse_fontindex() {
|
|
|
|
string s = get_tag_value();
|
|
|
|
|
|
|
|
if (s.empty() || s == "-") {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
size_t ptr;
|
|
|
|
int ret = std::stoi(s, &ptr, 10);
|
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ptr != s.size()) {
|
|
|
|
throw font_error(s, "Font index contains non-number characters");
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
} catch (const std::exception& err) {
|
|
|
|
throw font_error(s, err.what());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add units support (POINT, PIXEL, SPACE) (#2578)
* add units support (POINT, PIXEL, SPACE) for polybar
- add a size_with_unit struct
- add a geometry_format_values struct
- move dpi initialisation from renderer.cpp to bar.cpp
- add a string to size_with_unit converter
- add point support (with pt)
- add pixel support (with px)
* Fix unit test compilation
* clang-format
* Better names
The old names didn't really capture the purpose of the structs and
function.
space_type -> spacing_type
space_size -> spacing_val
size_type -> extent_type
geometry -> extent_val
geometry_format_values -> percentage_with_offset
* Remove parse_size_with_unit
No longer needed. The convert<spacing_val> function in config.cpp
already does all the work for us and always setting the type to pixel
was wrong.
In addition, line-size should not be of type spacing_val but extent_val.
* Cleanup
I tried to address most of my comments on the old PR
* Fix renderer width calculation
We can't just blindly add the x difference to the width because for
example the width should increase if x < width and the increase keeps
x < width.
Similarly, we can't just add the offset to the width.
* Rename geom_format_to_pixels to percentage_with_offset_to_pixel
* Cleanup
* Apply suggested changes from Patrick on GitHub
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/bar.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/config.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/builder.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/builder.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* config: Use stod for parsing percentage
* Use stof instead of strtof
* units: Fix test edge cases
* Remove unnecessary clang-format toggle
* Use percentage_with_offset for margin-{top,bottom}
* Support negative extent values
* Rename unit to units and create a cpp file
* Move percentage_with_offset_to_pixel unit test to units
* Add unit tests for units_utils
* Clarify when and how negative spacing/extent is allowed
Negative spacing is never allowed and produces a config error.
Extents allow negative values in theory, but only a few use-cases accept
it.
Only the extent value used for the `%{O}` tag and the offset value in
percentage_with_offset can be negative. Everything else is capped below
at 0.
The final pixel value of percentage_with_offset also caps below at 0.
* Fix parsing errors not being caught in config
* Print a proper error message for uncaught exceptions
* Cleanup module::get_output
All changes preserve the existing semantics
* Stop using remove_trailing_space in module::get_output
Instead, we first check if the current tag is built, and only if it is,
the spacing is prepended.
* Remove unused imports
* Restore old behavior
If there are two tags and the second one isn't built (module::build
returns false), the space in between them is removed.
For example in the mpd module:
format-online = <toggle> <label-song> foo
If mpd is not running, the mpd module will return false when trying to
build the `<label-song>` tag. If we don't remove the space between
`<toggle>` and `<label-song>`, we end up with two spaces between
`<toggle>` and `foo`.
This change is to match the old behavior where at least one trailing
space character was removed from the builder.
* Add changelog entry
* Remove unused setting
* Use percentage with offset for tray-offset
Co-authored-by: Jérôme BOULMIER <jerome.boulmier@outlook.fr>
Co-authored-by: Joe Groocock <github@frebib.net>
2022-02-20 20:08:57 +00:00
|
|
|
extent_val parser::parse_offset() {
|
2020-12-17 19:37:28 +00:00
|
|
|
string s = get_tag_value();
|
|
|
|
|
|
|
|
if (s.empty()) {
|
Add units support (POINT, PIXEL, SPACE) (#2578)
* add units support (POINT, PIXEL, SPACE) for polybar
- add a size_with_unit struct
- add a geometry_format_values struct
- move dpi initialisation from renderer.cpp to bar.cpp
- add a string to size_with_unit converter
- add point support (with pt)
- add pixel support (with px)
* Fix unit test compilation
* clang-format
* Better names
The old names didn't really capture the purpose of the structs and
function.
space_type -> spacing_type
space_size -> spacing_val
size_type -> extent_type
geometry -> extent_val
geometry_format_values -> percentage_with_offset
* Remove parse_size_with_unit
No longer needed. The convert<spacing_val> function in config.cpp
already does all the work for us and always setting the type to pixel
was wrong.
In addition, line-size should not be of type spacing_val but extent_val.
* Cleanup
I tried to address most of my comments on the old PR
* Fix renderer width calculation
We can't just blindly add the x difference to the width because for
example the width should increase if x < width and the increase keeps
x < width.
Similarly, we can't just add the offset to the width.
* Rename geom_format_to_pixels to percentage_with_offset_to_pixel
* Cleanup
* Apply suggested changes from Patrick on GitHub
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/bar.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/config.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/builder.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/builder.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* config: Use stod for parsing percentage
* Use stof instead of strtof
* units: Fix test edge cases
* Remove unnecessary clang-format toggle
* Use percentage_with_offset for margin-{top,bottom}
* Support negative extent values
* Rename unit to units and create a cpp file
* Move percentage_with_offset_to_pixel unit test to units
* Add unit tests for units_utils
* Clarify when and how negative spacing/extent is allowed
Negative spacing is never allowed and produces a config error.
Extents allow negative values in theory, but only a few use-cases accept
it.
Only the extent value used for the `%{O}` tag and the offset value in
percentage_with_offset can be negative. Everything else is capped below
at 0.
The final pixel value of percentage_with_offset also caps below at 0.
* Fix parsing errors not being caught in config
* Print a proper error message for uncaught exceptions
* Cleanup module::get_output
All changes preserve the existing semantics
* Stop using remove_trailing_space in module::get_output
Instead, we first check if the current tag is built, and only if it is,
the spacing is prepended.
* Remove unused imports
* Restore old behavior
If there are two tags and the second one isn't built (module::build
returns false), the space in between them is removed.
For example in the mpd module:
format-online = <toggle> <label-song> foo
If mpd is not running, the mpd module will return false when trying to
build the `<label-song>` tag. If we don't remove the space between
`<toggle>` and `<label-song>`, we end up with two spaces between
`<toggle>` and `foo`.
This change is to match the old behavior where at least one trailing
space character was removed from the builder.
* Add changelog entry
* Remove unused setting
* Use percentage with offset for tray-offset
Co-authored-by: Jérôme BOULMIER <jerome.boulmier@outlook.fr>
Co-authored-by: Joe Groocock <github@frebib.net>
2022-02-20 20:08:57 +00:00
|
|
|
return ZERO_PX_EXTENT;
|
2020-12-17 19:37:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
Add units support (POINT, PIXEL, SPACE) (#2578)
* add units support (POINT, PIXEL, SPACE) for polybar
- add a size_with_unit struct
- add a geometry_format_values struct
- move dpi initialisation from renderer.cpp to bar.cpp
- add a string to size_with_unit converter
- add point support (with pt)
- add pixel support (with px)
* Fix unit test compilation
* clang-format
* Better names
The old names didn't really capture the purpose of the structs and
function.
space_type -> spacing_type
space_size -> spacing_val
size_type -> extent_type
geometry -> extent_val
geometry_format_values -> percentage_with_offset
* Remove parse_size_with_unit
No longer needed. The convert<spacing_val> function in config.cpp
already does all the work for us and always setting the type to pixel
was wrong.
In addition, line-size should not be of type spacing_val but extent_val.
* Cleanup
I tried to address most of my comments on the old PR
* Fix renderer width calculation
We can't just blindly add the x difference to the width because for
example the width should increase if x < width and the increase keeps
x < width.
Similarly, we can't just add the offset to the width.
* Rename geom_format_to_pixels to percentage_with_offset_to_pixel
* Cleanup
* Apply suggested changes from Patrick on GitHub
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/bar.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/config.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/builder.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/builder.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* config: Use stod for parsing percentage
* Use stof instead of strtof
* units: Fix test edge cases
* Remove unnecessary clang-format toggle
* Use percentage_with_offset for margin-{top,bottom}
* Support negative extent values
* Rename unit to units and create a cpp file
* Move percentage_with_offset_to_pixel unit test to units
* Add unit tests for units_utils
* Clarify when and how negative spacing/extent is allowed
Negative spacing is never allowed and produces a config error.
Extents allow negative values in theory, but only a few use-cases accept
it.
Only the extent value used for the `%{O}` tag and the offset value in
percentage_with_offset can be negative. Everything else is capped below
at 0.
The final pixel value of percentage_with_offset also caps below at 0.
* Fix parsing errors not being caught in config
* Print a proper error message for uncaught exceptions
* Cleanup module::get_output
All changes preserve the existing semantics
* Stop using remove_trailing_space in module::get_output
Instead, we first check if the current tag is built, and only if it is,
the spacing is prepended.
* Remove unused imports
* Restore old behavior
If there are two tags and the second one isn't built (module::build
returns false), the space in between them is removed.
For example in the mpd module:
format-online = <toggle> <label-song> foo
If mpd is not running, the mpd module will return false when trying to
build the `<label-song>` tag. If we don't remove the space between
`<toggle>` and `<label-song>`, we end up with two spaces between
`<toggle>` and `foo`.
This change is to match the old behavior where at least one trailing
space character was removed from the builder.
* Add changelog entry
* Remove unused setting
* Use percentage with offset for tray-offset
Co-authored-by: Jérôme BOULMIER <jerome.boulmier@outlook.fr>
Co-authored-by: Joe Groocock <github@frebib.net>
2022-02-20 20:08:57 +00:00
|
|
|
return units_utils::parse_extent(string{s});
|
2020-12-17 19:37:28 +00:00
|
|
|
} catch (const std::exception& err) {
|
|
|
|
throw offset_error(s, err.what());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
controltag parser::parse_control() {
|
|
|
|
string s = get_tag_value();
|
|
|
|
|
|
|
|
if (s.empty()) {
|
|
|
|
throw control_error(s, "Control tag is empty");
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (s[0]) {
|
|
|
|
case 'R':
|
|
|
|
if (s.size() != 1) {
|
|
|
|
throw control_error(s, "Control tag R has extra data");
|
|
|
|
}
|
|
|
|
|
|
|
|
return controltag::R;
|
2022-04-15 21:50:04 +00:00
|
|
|
case 't':
|
|
|
|
return controltag::t;
|
2020-12-17 19:37:28 +00:00
|
|
|
default:
|
|
|
|
throw control_error(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<action_value, string> parser::parse_action() {
|
|
|
|
mousebtn btn = parse_action_btn();
|
|
|
|
|
|
|
|
action_value ret;
|
|
|
|
|
|
|
|
string cmd;
|
|
|
|
|
|
|
|
if (has_next() && peek() == ':') {
|
|
|
|
ret.btn = btn == mousebtn::NONE ? mousebtn::LEFT : btn;
|
|
|
|
ret.closing = false;
|
|
|
|
cmd = parse_action_cmd();
|
|
|
|
} else {
|
|
|
|
ret.btn = btn;
|
|
|
|
ret.closing = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {ret, cmd};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parses the button index after starting an action tag.
|
|
|
|
*
|
|
|
|
* May return mousebtn::NONE if no button was given.
|
|
|
|
*/
|
|
|
|
mousebtn parser::parse_action_btn() {
|
|
|
|
if (has_next()) {
|
|
|
|
if (isdigit(peek())) {
|
|
|
|
char c = next();
|
|
|
|
int num = c - '0';
|
|
|
|
|
|
|
|
if (num < static_cast<int>(mousebtn::NONE) || num >= static_cast<int>(mousebtn::BTN_COUNT)) {
|
|
|
|
throw btn_error(string{c});
|
|
|
|
}
|
|
|
|
|
|
|
|
return static_cast<mousebtn>(num);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return mousebtn::NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts at ':' and parses a complete action string.
|
|
|
|
*
|
|
|
|
* Returns the parsed action string with without escaping backslashes.
|
|
|
|
*
|
|
|
|
* Afterwards the parsers will be at the character immediately after the
|
|
|
|
* closing colon.
|
|
|
|
*/
|
|
|
|
string parser::parse_action_cmd() {
|
|
|
|
consume(':');
|
|
|
|
|
|
|
|
string s;
|
|
|
|
|
|
|
|
char prev = EOL;
|
|
|
|
|
|
|
|
while (has_next()) {
|
|
|
|
char c = next();
|
|
|
|
|
|
|
|
if (c == ':') {
|
|
|
|
if (prev == '\\') {
|
|
|
|
s.pop_back();
|
|
|
|
s.push_back(c);
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
s.push_back(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
prev = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
attribute parser::parse_attribute() {
|
|
|
|
char c;
|
|
|
|
switch (c = next()) {
|
|
|
|
case 'u':
|
|
|
|
return attribute::UNDERLINE;
|
|
|
|
case 'o':
|
|
|
|
return attribute::OVERLINE;
|
|
|
|
default:
|
|
|
|
throw unrecognized_attr(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void parser::push_char(char c) {
|
|
|
|
if (!buf.empty() && buf_pos < buf.size() && !buf.back().is_tag) {
|
|
|
|
buf.back().data += c;
|
|
|
|
} else {
|
|
|
|
buf.emplace_back(string{c});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void parser::push_text(string&& text) {
|
|
|
|
if (text.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!buf.empty() && buf_pos < buf.size() && !buf.back().is_tag) {
|
|
|
|
buf.back().data += text;
|
|
|
|
} else {
|
|
|
|
buf.emplace_back(std::move(text));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Will read up until the end of the tag value.
|
|
|
|
*
|
|
|
|
* Afterwards the parser will be at the character directly after the tag
|
|
|
|
* value.
|
|
|
|
*
|
|
|
|
* This function just reads until it encounters a space or a closing curly
|
|
|
|
* bracket, so it is not useful for tag values that can contain these
|
|
|
|
* characters (e.g. action tags).
|
|
|
|
*/
|
|
|
|
string parser::get_tag_value() {
|
|
|
|
string s;
|
|
|
|
|
|
|
|
while (has_next() && peek() != ' ' && peek() != '}') {
|
|
|
|
s.push_back(next());
|
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
Add units support (POINT, PIXEL, SPACE) (#2578)
* add units support (POINT, PIXEL, SPACE) for polybar
- add a size_with_unit struct
- add a geometry_format_values struct
- move dpi initialisation from renderer.cpp to bar.cpp
- add a string to size_with_unit converter
- add point support (with pt)
- add pixel support (with px)
* Fix unit test compilation
* clang-format
* Better names
The old names didn't really capture the purpose of the structs and
function.
space_type -> spacing_type
space_size -> spacing_val
size_type -> extent_type
geometry -> extent_val
geometry_format_values -> percentage_with_offset
* Remove parse_size_with_unit
No longer needed. The convert<spacing_val> function in config.cpp
already does all the work for us and always setting the type to pixel
was wrong.
In addition, line-size should not be of type spacing_val but extent_val.
* Cleanup
I tried to address most of my comments on the old PR
* Fix renderer width calculation
We can't just blindly add the x difference to the width because for
example the width should increase if x < width and the increase keeps
x < width.
Similarly, we can't just add the offset to the width.
* Rename geom_format_to_pixels to percentage_with_offset_to_pixel
* Cleanup
* Apply suggested changes from Patrick on GitHub
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/bar.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/config.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/builder.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* Update src/components/builder.cpp
Co-authored-by: Patrick Ziegler <p.ziegler96@gmail.com>
* config: Use stod for parsing percentage
* Use stof instead of strtof
* units: Fix test edge cases
* Remove unnecessary clang-format toggle
* Use percentage_with_offset for margin-{top,bottom}
* Support negative extent values
* Rename unit to units and create a cpp file
* Move percentage_with_offset_to_pixel unit test to units
* Add unit tests for units_utils
* Clarify when and how negative spacing/extent is allowed
Negative spacing is never allowed and produces a config error.
Extents allow negative values in theory, but only a few use-cases accept
it.
Only the extent value used for the `%{O}` tag and the offset value in
percentage_with_offset can be negative. Everything else is capped below
at 0.
The final pixel value of percentage_with_offset also caps below at 0.
* Fix parsing errors not being caught in config
* Print a proper error message for uncaught exceptions
* Cleanup module::get_output
All changes preserve the existing semantics
* Stop using remove_trailing_space in module::get_output
Instead, we first check if the current tag is built, and only if it is,
the spacing is prepended.
* Remove unused imports
* Restore old behavior
If there are two tags and the second one isn't built (module::build
returns false), the space in between them is removed.
For example in the mpd module:
format-online = <toggle> <label-song> foo
If mpd is not running, the mpd module will return false when trying to
build the `<label-song>` tag. If we don't remove the space between
`<toggle>` and `<label-song>`, we end up with two spaces between
`<toggle>` and `foo`.
This change is to match the old behavior where at least one trailing
space character was removed from the builder.
* Add changelog entry
* Remove unused setting
* Use percentage with offset for tray-offset
Co-authored-by: Jérôme BOULMIER <jerome.boulmier@outlook.fr>
Co-authored-by: Joe Groocock <github@frebib.net>
2022-02-20 20:08:57 +00:00
|
|
|
} // namespace tags
|
2020-12-17 19:37:28 +00:00
|
|
|
|
|
|
|
POLYBAR_NS_END
|