Skip to content

Commit 87c5a18

Browse files
authored
akarin.Text: Support float precision formatting syntax (e.g. {MyFrameProp:.4f} (#24)
* akarin.Text: Support float precision formatting syntax * Update textfilter.cpp
1 parent 0b4a71d commit 87c5a18

2 files changed

Lines changed: 26 additions & 2 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ Text is an enhanced `text.Text`:
136136
- `{N}`: The predefined `N` is the current frame number (if you want to access a frame property named `N`, use the full form `{x.N}` instead.
137137
- `"Matrix: {x._Matrix}"`: it will show the matrix property in string format (i.e. `Matrix: BT.709`).
138138
- `"Matrix: {x._Matrix:d}"`: it will show the matrix property as a number.
139+
- `"Value: {x.SomeFloat:.4f}"`: it will show a float property with four digits after the decimal point.
139140
- `"Chroma: {x._ChromaLocation:.>10s}`: it will show the chroma location as a string, right aligned, and padded on the left with '.' (i.e. `Chroma: ......Left`).
140141

141142
The filter supports formatting int/float scalar or arrays, data (shown as string). All the rest are shown as type sepcific placeholders (e.g. `<node>` for a node).

text/textfilter.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,8 @@ struct CustomValue {
323323
CustomValue(int val, std::string (*fptr)(int)): val(val), fptr(fptr) {}
324324
};
325325

326+
struct ValidationValue {}; // Accepts format specifications before the property type is known.
327+
326328
struct MissingValue {
327329
std::string s;
328330
MissingValue(std::string s): s(s) {}
@@ -353,23 +355,44 @@ template <> struct formatter<CustomValue>: public formatter<int>, formatter<stri
353355
return formatter<int>::format(p.val, ctx);
354356
}
355357
};
356-
template <> struct formatter<MissingValue>: public formatter<int>, formatter<string_view> {
358+
template <> struct formatter<ValidationValue> {
359+
auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) {
360+
return std::find(ctx.begin(), ctx.end(), '}');
361+
}
362+
363+
template <typename FormatContext>
364+
auto format(const ValidationValue &, FormatContext &ctx) -> decltype(ctx.out()) {
365+
return ctx.out();
366+
}
367+
};
368+
template <> struct formatter<MissingValue>: public formatter<int>, formatter<double>, formatter<string_view> {
357369
bool asString;
370+
bool asFloat;
358371
auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) {
359372
auto it = ctx.begin(), end = std::find(it, ctx.end(), '}');
360373
asString = true;
374+
asFloat = false;
361375
if (it == end) return it;
362376
if (*(end-1) == 's') {
363377
return formatter<string_view>::parse(ctx);
364378
}
365379
asString = false;
380+
char type = *(end-1);
381+
auto precision = std::find(it, end, '.');
382+
if (precision == it && precision + 1 != end && (*(precision + 1) == '<' || *(precision + 1) == '>' || *(precision + 1) == '^'))
383+
precision = std::find(precision + 2, end, '.'); // Ignore a dot used as the fill character before alignment.
384+
asFloat = precision != end || type == 'a' || type == 'A' || type == 'e' || type == 'E' || type == 'f' || type == 'F' || type == 'g' || type == 'G';
385+
if (asFloat)
386+
return formatter<double>::parse(ctx);
366387
return formatter<int>::parse(ctx);
367388
}
368389

369390
template <typename FormatContext>
370391
auto format(const MissingValue &p, FormatContext &ctx) -> decltype(ctx.out()) {
371392
if (asString)
372393
return formatter<string_view>::format(p.s, ctx);
394+
if (asFloat)
395+
return formatter<double>::format(0.0, ctx);
373396
return formatter<int>::format(0, ctx);
374397
}
375398
};
@@ -404,7 +427,7 @@ std::vector<PropAccess> checkFormatString(const std::string f) {
404427
vformat_to(std::back_inserter(null), f, store);
405428
} catch (fmt::missing_arg &e) {
406429
std::string id = e.what();
407-
store.push_back(fmt::arg(id.c_str(), CustomValue(1.0, matrixToString)));
430+
store.push_back(fmt::arg(id.c_str(), ValidationValue()));
408431
if (std::regex_match(id, match, framePropRe)) {
409432
auto clip = match[1].str(), name = match[2].str();
410433
int clipi = extractClipId(clip);

0 commit comments

Comments
 (0)