Did a full code coverage review and improved many of the tests and a bunch of code. I'll do one more final walk through all the code before getting back to work on the new combat system.
parent
113a4a3b3e
commit
d3158291f7
@ -1,376 +0,0 @@ |
|||||||
|
|
||||||
#line 1 "ansi_parser.rl" |
|
||||||
#include <fmt/core.h> |
|
||||||
#include <string_view> |
|
||||||
#include "dbc.hpp" |
|
||||||
#include <SFML/Graphics.hpp> |
|
||||||
#include "ansi_parser.hpp" |
|
||||||
#include <iostream> |
|
||||||
|
|
||||||
using namespace fmt; |
|
||||||
|
|
||||||
|
|
||||||
#line 122 "ansi_parser.rl" |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#line 13 "ansi_parser.cpp" |
|
||||||
static const char _ansi_parser_actions[] = { |
|
||||||
0, 1, 0, 1, 3, 1, 4, 1, |
|
||||||
5, 1, 6, 1, 7, 1, 8, 1, |
|
||||||
9, 1, 10, 1, 11, 1, 15, 1, |
|
||||||
16, 2, 1, 12, 2, 1, 13, 2, |
|
||||||
6, 7, 2, 16, 5, 3, 1, 14, |
|
||||||
2 |
|
||||||
}; |
|
||||||
|
|
||||||
static const char _ansi_parser_key_offsets[] = { |
|
||||||
0, 0, 1, 2, 11, 12, 14, 17, |
|
||||||
18, 22, 23, 27, 28, 29, 30, 31, |
|
||||||
33, 36, 38, 41, 43, 46, 47, 50, |
|
||||||
51, 52, 53, 54, 55 |
|
||||||
}; |
|
||||||
|
|
||||||
static const int _ansi_parser_trans_keys[] = { |
|
||||||
27, 91, 48, 49, 50, 51, 52, 55, |
|
||||||
57, 53, 54, 109, 48, 109, 34, 48, |
|
||||||
55, 109, 50, 52, 55, 109, 109, 49, |
|
||||||
56, 57, 109, 109, 59, 50, 59, 48, |
|
||||||
57, 59, 48, 57, 48, 57, 59, 48, |
|
||||||
57, 48, 57, 109, 48, 57, 109, 56, |
|
||||||
57, 109, 59, 50, 109, 109, 27, 27, |
|
||||||
0 |
|
||||||
}; |
|
||||||
|
|
||||||
static const char _ansi_parser_single_lengths[] = { |
|
||||||
0, 1, 1, 7, 1, 2, 3, 1, |
|
||||||
4, 1, 4, 1, 1, 1, 1, 0, |
|
||||||
1, 0, 1, 0, 1, 1, 3, 1, |
|
||||||
1, 1, 1, 1, 1 |
|
||||||
}; |
|
||||||
|
|
||||||
static const char _ansi_parser_range_lengths[] = { |
|
||||||
0, 0, 0, 1, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 1, |
|
||||||
1, 1, 1, 1, 1, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 0 |
|
||||||
}; |
|
||||||
|
|
||||||
static const char _ansi_parser_index_offsets[] = { |
|
||||||
0, 0, 2, 4, 13, 15, 18, 22, |
|
||||||
24, 29, 31, 36, 38, 40, 42, 44, |
|
||||||
46, 49, 51, 54, 56, 59, 61, 65, |
|
||||||
67, 69, 71, 73, 75 |
|
||||||
}; |
|
||||||
|
|
||||||
static const char _ansi_parser_trans_targs[] = { |
|
||||||
2, 1, 3, 0, 4, 5, 8, 10, |
|
||||||
22, 26, 6, 7, 0, 28, 0, 6, |
|
||||||
28, 0, 7, 7, 7, 0, 28, 0, |
|
||||||
7, 7, 9, 28, 0, 28, 0, 11, |
|
||||||
12, 21, 28, 0, 28, 0, 13, 0, |
|
||||||
14, 0, 15, 0, 16, 0, 17, 16, |
|
||||||
0, 18, 0, 19, 18, 0, 20, 0, |
|
||||||
28, 20, 0, 28, 0, 23, 25, 28, |
|
||||||
0, 24, 0, 14, 0, 28, 0, 28, |
|
||||||
0, 2, 1, 2, 1, 0 |
|
||||||
}; |
|
||||||
|
|
||||||
static const char _ansi_parser_trans_actions[] = { |
|
||||||
0, 7, 0, 0, 21, 21, 21, 21, |
|
||||||
21, 21, 21, 21, 0, 31, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 17, 0, 15, 0, 0, |
|
||||||
0, 0, 0, 0, 19, 0, 0, 0, |
|
||||||
3, 0, 0, 0, 1, 0, 25, 0, |
|
||||||
0, 1, 0, 28, 0, 0, 1, 0, |
|
||||||
37, 0, 0, 9, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 5, 0, 11, 0, 13, |
|
||||||
0, 0, 7, 23, 34, 0 |
|
||||||
}; |
|
||||||
|
|
||||||
static const char _ansi_parser_eof_actions[] = { |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, |
|
||||||
0, 0, 0, 0, 23 |
|
||||||
}; |
|
||||||
|
|
||||||
static const int ansi_parser_start = 27; |
|
||||||
static const int ansi_parser_first_final = 27; |
|
||||||
static const int ansi_parser_error = 0; |
|
||||||
|
|
||||||
static const int ansi_parser_en_main = 27; |
|
||||||
|
|
||||||
|
|
||||||
#line 125 "ansi_parser.rl" |
|
||||||
|
|
||||||
#include <ftxui/screen/terminal.hpp> |
|
||||||
|
|
||||||
ANSIParser::ANSIParser(sf::Color default_fg, sf::Color default_bg) : |
|
||||||
$default_fg(default_fg), |
|
||||||
$default_bg(default_bg) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
bool ANSIParser::parse(std::wstring_view codes, ColorCB color_cb, WriteCB write_cb) { |
|
||||||
const wchar_t *start = nullptr; |
|
||||||
int cs = 0; |
|
||||||
unsigned int value = 0; |
|
||||||
const wchar_t *p = codes.data(); |
|
||||||
const wchar_t *pe = p + codes.size(); |
|
||||||
const wchar_t *eof = pe; |
|
||||||
sf::Color bgcolor($default_bg); |
|
||||||
sf::Color color($default_fg); |
|
||||||
sf::Color* target = &color; |
|
||||||
|
|
||||||
|
|
||||||
#line 120 "ansi_parser.cpp" |
|
||||||
{ |
|
||||||
cs = ansi_parser_start; |
|
||||||
} |
|
||||||
|
|
||||||
#line 146 "ansi_parser.rl" |
|
||||||
|
|
||||||
#line 123 "ansi_parser.cpp" |
|
||||||
{ |
|
||||||
int _klen; |
|
||||||
unsigned int _trans; |
|
||||||
const char *_acts; |
|
||||||
unsigned int _nacts; |
|
||||||
const int *_keys; |
|
||||||
|
|
||||||
if ( p == pe ) |
|
||||||
goto _test_eof; |
|
||||||
if ( cs == 0 ) |
|
||||||
goto _out; |
|
||||||
_resume: |
|
||||||
_keys = _ansi_parser_trans_keys + _ansi_parser_key_offsets[cs]; |
|
||||||
_trans = _ansi_parser_index_offsets[cs]; |
|
||||||
|
|
||||||
_klen = _ansi_parser_single_lengths[cs]; |
|
||||||
if ( _klen > 0 ) { |
|
||||||
const int *_lower = _keys; |
|
||||||
const int *_mid; |
|
||||||
const int *_upper = _keys + _klen - 1; |
|
||||||
while (1) { |
|
||||||
if ( _upper < _lower ) |
|
||||||
break; |
|
||||||
|
|
||||||
_mid = _lower + ((_upper-_lower) >> 1); |
|
||||||
if ( (*p) < *_mid ) |
|
||||||
_upper = _mid - 1; |
|
||||||
else if ( (*p) > *_mid ) |
|
||||||
_lower = _mid + 1; |
|
||||||
else { |
|
||||||
_trans += (unsigned int)(_mid - _keys); |
|
||||||
goto _match; |
|
||||||
} |
|
||||||
} |
|
||||||
_keys += _klen; |
|
||||||
_trans += _klen; |
|
||||||
} |
|
||||||
|
|
||||||
_klen = _ansi_parser_range_lengths[cs]; |
|
||||||
if ( _klen > 0 ) { |
|
||||||
const int *_lower = _keys; |
|
||||||
const int *_mid; |
|
||||||
const int *_upper = _keys + (_klen<<1) - 2; |
|
||||||
while (1) { |
|
||||||
if ( _upper < _lower ) |
|
||||||
break; |
|
||||||
|
|
||||||
_mid = _lower + (((_upper-_lower) >> 1) & ~1); |
|
||||||
if ( (*p) < _mid[0] ) |
|
||||||
_upper = _mid - 2; |
|
||||||
else if ( (*p) > _mid[1] ) |
|
||||||
_lower = _mid + 2; |
|
||||||
else { |
|
||||||
_trans += (unsigned int)((_mid - _keys)>>1); |
|
||||||
goto _match; |
|
||||||
} |
|
||||||
} |
|
||||||
_trans += _klen; |
|
||||||
} |
|
||||||
|
|
||||||
_match: |
|
||||||
cs = _ansi_parser_trans_targs[_trans]; |
|
||||||
|
|
||||||
if ( _ansi_parser_trans_actions[_trans] == 0 ) |
|
||||||
goto _again; |
|
||||||
|
|
||||||
_acts = _ansi_parser_actions + _ansi_parser_trans_actions[_trans]; |
|
||||||
_nacts = (unsigned int) *_acts++; |
|
||||||
while ( _nacts-- > 0 ) |
|
||||||
{ |
|
||||||
switch ( *_acts++ ) |
|
||||||
{ |
|
||||||
case 0: |
|
||||||
#line 14 "ansi_parser.rl" |
|
||||||
{ |
|
||||||
start = p; |
|
||||||
} |
|
||||||
break; |
|
||||||
case 1: |
|
||||||
#line 18 "ansi_parser.rl" |
|
||||||
{ |
|
||||||
value = 0; |
|
||||||
size_t len = p - start; |
|
||||||
dbc::check(start[0] != '-', "negative numbers not supported"); |
|
||||||
|
|
||||||
switch(len) { |
|
||||||
case 10: value += (start[len-10] - '0') * 1000000000; [[fallthrough]]; |
|
||||||
case 9: value += (start[len- 9] - '0') * 100000000; [[fallthrough]]; |
|
||||||
case 8: value += (start[len- 8] - '0') * 10000000; [[fallthrough]]; |
|
||||||
case 7: value += (start[len- 7] - '0') * 1000000; [[fallthrough]]; |
|
||||||
case 6: value += (start[len- 6] - '0') * 100000; [[fallthrough]]; |
|
||||||
case 5: value += (start[len- 5] - '0') * 10000; [[fallthrough]]; |
|
||||||
case 4: value += (start[len- 4] - '0') * 1000; [[fallthrough]]; |
|
||||||
case 3: value += (start[len- 3] - '0') * 100; [[fallthrough]]; |
|
||||||
case 2: value += (start[len- 2] - '0') * 10; [[fallthrough]]; |
|
||||||
case 1: value += (start[len- 1] - '0'); |
|
||||||
break; |
|
||||||
default: |
|
||||||
dbc::sentinel("can't process > 10 digits"); |
|
||||||
} |
|
||||||
} |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
#line 40 "ansi_parser.rl" |
|
||||||
{ |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
break; |
|
||||||
case 3: |
|
||||||
#line 43 "ansi_parser.rl" |
|
||||||
{ |
|
||||||
target = &color; |
|
||||||
} |
|
||||||
break; |
|
||||||
case 4: |
|
||||||
#line 46 "ansi_parser.rl" |
|
||||||
{ |
|
||||||
target = &bgcolor; |
|
||||||
} |
|
||||||
break; |
|
||||||
case 5: |
|
||||||
#line 50 "ansi_parser.rl" |
|
||||||
{ |
|
||||||
write_cb((*p)); |
|
||||||
} |
|
||||||
break; |
|
||||||
case 6: |
|
||||||
#line 54 "ansi_parser.rl" |
|
||||||
{ |
|
||||||
color = $default_fg; |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
break; |
|
||||||
case 7: |
|
||||||
#line 58 "ansi_parser.rl" |
|
||||||
{ |
|
||||||
bgcolor = $default_bg; |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
break; |
|
||||||
case 8: |
|
||||||
#line 62 "ansi_parser.rl" |
|
||||||
{ |
|
||||||
color = $default_bg; |
|
||||||
bgcolor = $default_fg; |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
break; |
|
||||||
case 9: |
|
||||||
#line 67 "ansi_parser.rl" |
|
||||||
{ |
|
||||||
color = $default_fg; |
|
||||||
bgcolor = $default_bg; |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
break; |
|
||||||
case 10: |
|
||||||
#line 72 "ansi_parser.rl" |
|
||||||
{ |
|
||||||
color = sf::Color(100,100,100); |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
break; |
|
||||||
case 11: |
|
||||||
#line 76 "ansi_parser.rl" |
|
||||||
{ |
|
||||||
color = sf::Color::Red; |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
break; |
|
||||||
case 12: |
|
||||||
#line 81 "ansi_parser.rl" |
|
||||||
{ target->r = value; } |
|
||||||
break; |
|
||||||
case 13: |
|
||||||
#line 82 "ansi_parser.rl" |
|
||||||
{ target->g = value; } |
|
||||||
break; |
|
||||||
case 14: |
|
||||||
#line 83 "ansi_parser.rl" |
|
||||||
{ target->b = value; } |
|
||||||
break; |
|
||||||
case 15: |
|
||||||
#line 84 "ansi_parser.rl" |
|
||||||
{ value = 0; } |
|
||||||
break; |
|
||||||
case 16: |
|
||||||
#line 85 "ansi_parser.rl" |
|
||||||
{} |
|
||||||
break; |
|
||||||
#line 296 "ansi_parser.cpp" |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
_again: |
|
||||||
if ( cs == 0 ) |
|
||||||
goto _out; |
|
||||||
if ( ++p != pe ) |
|
||||||
goto _resume; |
|
||||||
_test_eof: {} |
|
||||||
if ( p == eof ) |
|
||||||
{ |
|
||||||
const char *__acts = _ansi_parser_actions + _ansi_parser_eof_actions[cs]; |
|
||||||
unsigned int __nacts = (unsigned int) *__acts++; |
|
||||||
while ( __nacts-- > 0 ) { |
|
||||||
switch ( *__acts++ ) { |
|
||||||
case 16: |
|
||||||
#line 85 "ansi_parser.rl" |
|
||||||
{} |
|
||||||
break; |
|
||||||
#line 314 "ansi_parser.cpp" |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
_out: {} |
|
||||||
} |
|
||||||
|
|
||||||
#line 147 "ansi_parser.rl" |
|
||||||
|
|
||||||
bool good = pe - p == 0; |
|
||||||
|
|
||||||
if(!good) { |
|
||||||
p -= 10; |
|
||||||
// dear cthuhlu, save me from the pain that is wstring
|
|
||||||
for(int i = 0; i < 100; i++) { |
|
||||||
try { |
|
||||||
print("{}", p[i] == 0x1B ? '^' : char(p[i])); |
|
||||||
} catch(...) { |
|
||||||
print("?=", int(p[i])); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
(void)ansi_parser_first_final; |
|
||||||
(void)ansi_parser_error; |
|
||||||
(void)ansi_parser_en_main; |
|
||||||
|
|
||||||
|
|
||||||
return good; |
|
||||||
} |
|
@ -1,23 +0,0 @@ |
|||||||
#pragma once |
|
||||||
#include <string_view> |
|
||||||
#include <SFML/Graphics.hpp> |
|
||||||
#include <codecvt> |
|
||||||
#include <functional> |
|
||||||
|
|
||||||
typedef std::function<void(sf::Color bgcolor, sf::Color color)> ColorCB; |
|
||||||
|
|
||||||
typedef std::function<void(wchar_t ch)> WriteCB; |
|
||||||
|
|
||||||
class ANSIParser { |
|
||||||
sf::Color $default_fg; |
|
||||||
sf::Color $default_bg; |
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> $converter; |
|
||||||
|
|
||||||
public: |
|
||||||
ANSIParser(sf::Color default_fg, sf::Color default_bg); |
|
||||||
|
|
||||||
// disable copying
|
|
||||||
ANSIParser(ANSIParser& ap) = delete; |
|
||||||
|
|
||||||
bool parse(std::wstring_view codes, ColorCB color_cb, WriteCB write_cb); |
|
||||||
}; |
|
@ -1,167 +0,0 @@ |
|||||||
#include <fmt/core.h> |
|
||||||
#include <string_view> |
|
||||||
#include "dbc.hpp" |
|
||||||
#include <SFML/Graphics.hpp> |
|
||||||
#include "ansi_parser.hpp" |
|
||||||
#include <iostream> |
|
||||||
|
|
||||||
using namespace fmt; |
|
||||||
|
|
||||||
%%{ |
|
||||||
machine ansi_parser; |
|
||||||
alphtype int; |
|
||||||
|
|
||||||
action tstart { |
|
||||||
start = fpc; |
|
||||||
} |
|
||||||
|
|
||||||
action number { |
|
||||||
value = 0; |
|
||||||
size_t len = fpc - start; |
|
||||||
dbc::check(start[0] != '-', "negative numbers not supported"); |
|
||||||
|
|
||||||
switch(len) { |
|
||||||
case 10: value += (start[len-10] - '0') * 1000000000; [[fallthrough]]; |
|
||||||
case 9: value += (start[len- 9] - '0') * 100000000; [[fallthrough]]; |
|
||||||
case 8: value += (start[len- 8] - '0') * 10000000; [[fallthrough]]; |
|
||||||
case 7: value += (start[len- 7] - '0') * 1000000; [[fallthrough]]; |
|
||||||
case 6: value += (start[len- 6] - '0') * 100000; [[fallthrough]]; |
|
||||||
case 5: value += (start[len- 5] - '0') * 10000; [[fallthrough]]; |
|
||||||
case 4: value += (start[len- 4] - '0') * 1000; [[fallthrough]]; |
|
||||||
case 3: value += (start[len- 3] - '0') * 100; [[fallthrough]]; |
|
||||||
case 2: value += (start[len- 2] - '0') * 10; [[fallthrough]]; |
|
||||||
case 1: value += (start[len- 1] - '0'); |
|
||||||
break; |
|
||||||
default: |
|
||||||
dbc::sentinel("can't process > 10 digits"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
action color_out { |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
action is_fg { |
|
||||||
target = &color; |
|
||||||
} |
|
||||||
action is_bg { |
|
||||||
target = &bgcolor; |
|
||||||
} |
|
||||||
|
|
||||||
action out { |
|
||||||
write_cb(fc); |
|
||||||
} |
|
||||||
|
|
||||||
action reset_fg { |
|
||||||
color = $default_fg; |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
action reset_bg { |
|
||||||
bgcolor = $default_bg; |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
action invert { |
|
||||||
color = $default_bg; |
|
||||||
bgcolor = $default_fg; |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
action reset_invert { |
|
||||||
color = $default_fg; |
|
||||||
bgcolor = $default_bg; |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
action half_bright { |
|
||||||
color = sf::Color(100,100,100); |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
action red_text { |
|
||||||
color = sf::Color::Red; |
|
||||||
color_cb(color, bgcolor); |
|
||||||
} |
|
||||||
|
|
||||||
action red { target->r = value; } |
|
||||||
action blue { target->g = value; } |
|
||||||
action green { target->b = value; } |
|
||||||
action start { value = 0; } |
|
||||||
action end {} |
|
||||||
action log { println("command {}", (char)fc); } |
|
||||||
|
|
||||||
ESC = 0x1B; |
|
||||||
start = ESC "["; |
|
||||||
fg = "38;" %is_fg; |
|
||||||
bg = "48;" %is_bg; |
|
||||||
reset = ("39" %reset_fg | "49" %reset_bg); |
|
||||||
num = digit+ >tstart %number; |
|
||||||
color256 = "5;"; |
|
||||||
color24b = "2;"; |
|
||||||
|
|
||||||
ansi = ( |
|
||||||
start %start |
|
||||||
( |
|
||||||
reset | |
|
||||||
"0" %reset_fg %reset_bg | |
|
||||||
"1" | |
|
||||||
"2" %half_bright | |
|
||||||
"3" | |
|
||||||
"4" | |
|
||||||
"5" | |
|
||||||
"6" | |
|
||||||
"7" %invert | |
|
||||||
"31" %red_text | |
|
||||||
"22" | |
|
||||||
"24" | |
|
||||||
"27" %reset_invert | |
|
||||||
"9" ["0"-"7"] | |
|
||||||
"10" ["0"-"7"] | |
|
||||||
(fg|bg) (color24b num %red ";" num %blue ";" num %green ) %color_out |
|
||||||
) "m" %end |
|
||||||
); |
|
||||||
|
|
||||||
other = (any+ @out -- ESC)*; |
|
||||||
|
|
||||||
main := (other :> ansi)**; |
|
||||||
}%% |
|
||||||
|
|
||||||
%% write data; |
|
||||||
|
|
||||||
#include <ftxui/screen/terminal.hpp> |
|
||||||
|
|
||||||
ANSIParser::ANSIParser(sf::Color default_fg, sf::Color default_bg) : |
|
||||||
$default_fg(default_fg), |
|
||||||
$default_bg(default_bg) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
bool ANSIParser::parse(std::wstring_view codes, ColorCB color_cb, WriteCB write_cb) { |
|
||||||
const wchar_t *start = nullptr; |
|
||||||
int cs = 0; |
|
||||||
unsigned int value = 0; |
|
||||||
const wchar_t *p = codes.data(); |
|
||||||
const wchar_t *pe = p + codes.size(); |
|
||||||
const wchar_t *eof = pe; |
|
||||||
sf::Color bgcolor($default_bg); |
|
||||||
sf::Color color($default_fg); |
|
||||||
sf::Color* target = &color; |
|
||||||
|
|
||||||
%% write init; |
|
||||||
%% write exec; |
|
||||||
|
|
||||||
bool good = pe - p == 0; |
|
||||||
|
|
||||||
if(!good) { |
|
||||||
p -= 10; |
|
||||||
// dear cthuhlu, save me from the pain that is wstring |
|
||||||
for(int i = 0; i < 100; i++) { |
|
||||||
try { |
|
||||||
print("{}", p[i] == 0x1B ? '^' : char(p[i])); |
|
||||||
} catch(...) { |
|
||||||
print("?=", int(p[i])); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
(void)ansi_parser_first_final; |
|
||||||
(void)ansi_parser_error; |
|
||||||
(void)ansi_parser_en_main; |
|
||||||
|
|
||||||
return good; |
|
||||||
} |
|
@ -1,64 +0,0 @@ |
|||||||
#include "panel.hpp" |
|
||||||
#include "dbc.hpp" |
|
||||||
|
|
||||||
void Panel::resize(int w, int h) { |
|
||||||
$dirty = true; |
|
||||||
width = w; |
|
||||||
height = h; |
|
||||||
$screen = Screen(width, height); |
|
||||||
} |
|
||||||
|
|
||||||
void Panel::set_renderer(Component renderer) { |
|
||||||
$dirty = true; |
|
||||||
$component = renderer; |
|
||||||
} |
|
||||||
|
|
||||||
void Panel::add(Component child) { |
|
||||||
dbc::pre("must set_renderer first", $component != nullptr); |
|
||||||
$dirty = true; |
|
||||||
$component->Add(child); |
|
||||||
} |
|
||||||
|
|
||||||
void Panel::render() { |
|
||||||
$dirty = true; |
|
||||||
if(must_clear) $screen.Clear(); |
|
||||||
Render($screen, $component->Render()); |
|
||||||
} |
|
||||||
|
|
||||||
const std::wstring& Panel::to_string() { |
|
||||||
if($dirty) { |
|
||||||
std::string as_text = $screen.ToString(); |
|
||||||
$screenout = $converter.from_bytes(as_text); |
|
||||||
$dirty = false; |
|
||||||
} |
|
||||||
|
|
||||||
return $screenout; |
|
||||||
} |
|
||||||
|
|
||||||
void Panel::mouse_click(ftxui::Mouse::Button btn, Point pos) { |
|
||||||
ftxui::Mouse mev{ |
|
||||||
.button=btn, |
|
||||||
.motion=ftxui::Mouse::Motion::Pressed, |
|
||||||
.x=int(pos.x), .y=int(pos.y) |
|
||||||
}; |
|
||||||
|
|
||||||
$component->OnEvent(ftxui::Event::Mouse("", mev)); |
|
||||||
} |
|
||||||
|
|
||||||
void Panel::mouse_release(ftxui::Mouse::Button btn, Point pos) { |
|
||||||
ftxui::Mouse mev{ |
|
||||||
.button=btn, |
|
||||||
.motion=ftxui::Mouse::Motion::Released, |
|
||||||
.x=int(pos.x), .y=int(pos.y) |
|
||||||
}; |
|
||||||
|
|
||||||
$component->OnEvent(ftxui::Event::Mouse("", mev)); |
|
||||||
} |
|
||||||
|
|
||||||
const Screen& Panel::screen() { |
|
||||||
return $screen; |
|
||||||
} |
|
||||||
|
|
||||||
void Panel::key_press(ftxui::Event event) { |
|
||||||
$component->OnEvent(event); |
|
||||||
} |
|
@ -1,60 +0,0 @@ |
|||||||
#pragma once |
|
||||||
#include <ftxui/dom/node.hpp> // for Render |
|
||||||
#include <ftxui/component/component.hpp> |
|
||||||
#include <ftxui/component/mouse.hpp> |
|
||||||
#include <ftxui/dom/canvas.hpp> |
|
||||||
#include <ftxui/screen/screen.hpp> |
|
||||||
#include <ftxui/dom/canvas.hpp> |
|
||||||
#include <ftxui/screen/screen.hpp> |
|
||||||
#include <ftxui/dom/canvas.hpp> |
|
||||||
#include <SFML/Graphics/Color.hpp> |
|
||||||
#include <locale> |
|
||||||
#include <codecvt> |
|
||||||
#include "color.hpp" |
|
||||||
#include "point.hpp" |
|
||||||
|
|
||||||
const int UI_PANEL_BORDER_PX=5; |
|
||||||
|
|
||||||
using ftxui::Renderer, ftxui::Component, ftxui::Element, ftxui::Screen; |
|
||||||
|
|
||||||
class Panel { |
|
||||||
public: |
|
||||||
int x; |
|
||||||
int y; |
|
||||||
int width; |
|
||||||
int height; |
|
||||||
bool has_border = false; |
|
||||||
bool must_clear = true; |
|
||||||
bool grid = false; |
|
||||||
sf::Color default_bg = ColorValue::BLACK; |
|
||||||
sf::Color default_fg = ColorValue::LIGHT_LIGHT; |
|
||||||
sf::Color border_color = ColorValue::MID; |
|
||||||
int border_px = UI_PANEL_BORDER_PX; |
|
||||||
|
|
||||||
bool $dirty = true; |
|
||||||
Component $component = nullptr; |
|
||||||
Screen $screen; |
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> $converter; |
|
||||||
std::wstring $screenout; |
|
||||||
|
|
||||||
Panel(int x, int y, int width, int height, bool is_grid=false) : |
|
||||||
x(x), |
|
||||||
y(y), |
|
||||||
width(width), |
|
||||||
height(height), |
|
||||||
grid(is_grid), |
|
||||||
$screen(Screen(width, height)) |
|
||||||
{ |
|
||||||
must_clear = !is_grid; |
|
||||||
}; |
|
||||||
|
|
||||||
void resize(int width, int height); |
|
||||||
void set_renderer(Component renderer); |
|
||||||
void add(Component child); |
|
||||||
void render(); |
|
||||||
void mouse_click(ftxui::Mouse::Button btn, Point pos); |
|
||||||
void mouse_release(ftxui::Mouse::Button btn, Point pos); |
|
||||||
void key_press(ftxui::Event event); |
|
||||||
const std::wstring &to_string(); |
|
||||||
const Screen &screen(); |
|
||||||
}; |
|
@ -1,275 +0,0 @@ |
|||||||
#include "render.hpp" |
|
||||||
#include "ansi_parser.hpp" |
|
||||||
#include <cmath> |
|
||||||
#include <fmt/core.h> |
|
||||||
#include <array> |
|
||||||
#include "map.hpp" |
|
||||||
#include <iostream> |
|
||||||
#include "color.hpp" |
|
||||||
|
|
||||||
#if defined(_WIN64) || defined(_WIN32) |
|
||||||
#include <stdio.h> |
|
||||||
#include <fcntl.h> |
|
||||||
#include <io.h> |
|
||||||
#endif |
|
||||||
|
|
||||||
using namespace fmt; |
|
||||||
|
|
||||||
SFMLRender::SFMLRender(sf::RenderWindow &window) : |
|
||||||
$window(window), |
|
||||||
$map_font_size(0), |
|
||||||
$line_spacing(0), |
|
||||||
$default_fg(ColorValue::LIGHT_MID), |
|
||||||
$default_bg(ColorValue::BLACK), |
|
||||||
$bg_sprite($font_texture), |
|
||||||
$font(FONT_FILE_NAME), |
|
||||||
$ui_text($font), |
|
||||||
$ansi($default_fg, $default_bg) |
|
||||||
{ |
|
||||||
// force true color, but maybe I want to support different color sets
|
|
||||||
$font.setSmooth(false); |
|
||||||
$ui_text.setPosition({0,0}); |
|
||||||
$ui_text.setCharacterSize($config.ui_font_size); |
|
||||||
$ui_text.setFillColor(ColorValue::LIGHT_MID); |
|
||||||
sf::Glyph glyph = $font.getGlyph($config.ui_base_char, $config.ui_font_size, false); |
|
||||||
$text_bounds = glyph.bounds; |
|
||||||
$cells_w = std::ceil($config.video_x / $text_bounds.size.x); |
|
||||||
$cells_h = std::ceil($config.video_y / $text_bounds.size.y); |
|
||||||
} |
|
||||||
|
|
||||||
sf::Sprite &SFMLRender::get_text_sprite(wchar_t tile) { |
|
||||||
if(!$sprites.contains(tile)) { |
|
||||||
sf::Glyph glyph = $font.getGlyph(tile, $map_font_size, false); |
|
||||||
// WARNING! we actually have to do this here because SFML caches
|
|
||||||
// the glyphs on the font texture, so this gets loaded each time
|
|
||||||
// we get a new glyph from the font.
|
|
||||||
$font_texture = $font.getTexture($map_font_size); |
|
||||||
$sprites.try_emplace(tile, $font_texture, glyph.textureRect); |
|
||||||
} |
|
||||||
|
|
||||||
return $sprites.at(tile); |
|
||||||
} |
|
||||||
|
|
||||||
void SFMLRender::clear_cache() { |
|
||||||
$sprites.clear(); |
|
||||||
bool good = $font.openFromFile(FONT_FILE_NAME); |
|
||||||
dbc::check(good, "Failed to load the font."); |
|
||||||
$font.setSmooth(false); |
|
||||||
$ui_text.setFont($font); |
|
||||||
} |
|
||||||
|
|
||||||
void SFMLRender::center_panel(Panel &panel) { |
|
||||||
int cell_center_x = ($cells_w - panel.width) / 2; |
|
||||||
int cell_center_y = ($cells_h - panel.height) / 2; |
|
||||||
|
|
||||||
panel.x = cell_center_x * $text_bounds.size.x; |
|
||||||
panel.y = cell_center_y * $text_bounds.size.y; |
|
||||||
} |
|
||||||
|
|
||||||
void SFMLRender::resize_grid(int new_size, Panel &panel_out) { |
|
||||||
auto glyph = $font.getGlyph($config.bg_tile, new_size, false); |
|
||||||
int view_x = std::ceil(($config.video_x - panel_out.x) / glyph.bounds.size.x); |
|
||||||
int view_y = std::ceil(($config.video_y - panel_out.y) / glyph.bounds.size.y); |
|
||||||
|
|
||||||
// looks good, set 'em all
|
|
||||||
$base_glyph = glyph; |
|
||||||
$map_font_size = new_size; |
|
||||||
$sprites.clear(); // need to reset the sprites for the new size
|
|
||||||
$line_spacing = $font.getLineSpacing($map_font_size); |
|
||||||
$bg_sprite = get_text_sprite($config.bg_tile); |
|
||||||
$grid_bounds = $bg_sprite.getLocalBounds(); |
|
||||||
panel_out.resize(view_x, view_y); |
|
||||||
} |
|
||||||
|
|
||||||
inline void configure_tile(const sf::Sprite &sprite, sf::FloatRect &sp_bounds, sf::FloatRect grid_bounds, float &width_delta, float &height_delta) { |
|
||||||
// BUG: I think I could create a struct that kept this info for all sprites loaded
|
|
||||||
// should look into caching all this instead of calcing it each time
|
|
||||||
sp_bounds = sprite.getLocalBounds(); |
|
||||||
|
|
||||||
// calculate where to center the sprite, but only if it's smaller
|
|
||||||
width_delta = grid_bounds.size.x > sp_bounds.size.x ? (grid_bounds.size.x - sp_bounds.size.x) / 2 : 0; |
|
||||||
height_delta = grid_bounds.size.y > sp_bounds.size.x ? (grid_bounds.size.y - sp_bounds.size.y) / 2 : 0; |
|
||||||
} |
|
||||||
|
|
||||||
void SFMLRender::render_grid(const std::wstring &text, sf::Color default_fg, sf::Color default_bg, float x, float y) { |
|
||||||
wchar_t last_tile = $config.bg_tile; |
|
||||||
sf::FloatRect sp_bounds; |
|
||||||
float width_delta = 0; |
|
||||||
float height_delta = 0; |
|
||||||
sf::Sprite &sprite = get_text_sprite(last_tile); |
|
||||||
const float start_x = x; |
|
||||||
sf::Color cur_fg = default_fg; |
|
||||||
sf::Color cur_bg = default_bg; |
|
||||||
|
|
||||||
$ansi.parse(text, [&](auto fg, auto bg) { |
|
||||||
cur_fg = fg; |
|
||||||
cur_bg = bg; |
|
||||||
}, |
|
||||||
|
|
||||||
[&](wchar_t tile) { |
|
||||||
switch(tile) { |
|
||||||
case '\r': break; // ignore it
|
|
||||||
case '\n': { |
|
||||||
// don't bother processing newlines, just skip
|
|
||||||
y += $line_spacing; |
|
||||||
x = start_x; |
|
||||||
} |
|
||||||
break; |
|
||||||
default: { |
|
||||||
// only get a new sprite if the tile changed
|
|
||||||
if(last_tile != tile) { |
|
||||||
sprite = get_text_sprite(tile); |
|
||||||
configure_tile(sprite, sp_bounds, $grid_bounds, width_delta, height_delta); |
|
||||||
last_tile = tile; // update last tile seen
|
|
||||||
} |
|
||||||
|
|
||||||
sprite.setPosition({x+width_delta, y+height_delta}); |
|
||||||
sprite.setColor(cur_fg); |
|
||||||
|
|
||||||
// only draw background char if it's different from default
|
|
||||||
if(cur_bg != default_bg) { |
|
||||||
$bg_sprite.setPosition({x, y}); |
|
||||||
$bg_sprite.setColor(cur_bg); |
|
||||||
$window.draw($bg_sprite); |
|
||||||
} |
|
||||||
|
|
||||||
$window.draw(sprite); |
|
||||||
// next cell
|
|
||||||
x += $base_glyph.advance; |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
inline sf::FloatRect draw_chunk(sf::RenderWindow& window, |
|
||||||
sf::FloatRect text_bounds, sf::Text& text, sf::Color default_bg, |
|
||||||
sf::Color bgcolor, int bg_box_offset, float x, float y, std::wstring &out) |
|
||||||
{ |
|
||||||
text.setString(out); |
|
||||||
text.setPosition({x, y}); |
|
||||||
// get a base character for the cell size
|
|
||||||
sf::FloatRect bounds({x, y}, {text_bounds.size.x * out.size(), text_bounds.size.y}); |
|
||||||
|
|
||||||
if(default_bg != bgcolor) { |
|
||||||
sf::RectangleShape backing(bounds.size); |
|
||||||
backing.setFillColor(bgcolor); |
|
||||||
backing.setPosition({bounds.position.x, bounds.position.y + bg_box_offset}); |
|
||||||
window.draw(backing); |
|
||||||
} |
|
||||||
|
|
||||||
window.draw(text); |
|
||||||
out.clear(); |
|
||||||
return bounds; |
|
||||||
} |
|
||||||
|
|
||||||
void SFMLRender::render_text(const std::wstring &text, sf::Color default_fg, sf::Color default_bg, float start_x, float start_y) { |
|
||||||
std::wstring out; |
|
||||||
float x = start_x; |
|
||||||
float y = start_y; |
|
||||||
sf::Color cur_bg = default_bg; |
|
||||||
|
|
||||||
// start with the default_fg until it's changed
|
|
||||||
$ui_text.setFillColor(default_fg); |
|
||||||
|
|
||||||
$ansi.parse(text, |
|
||||||
[&](auto fg, auto bg) { |
|
||||||
if(out.size() > 0 ) { |
|
||||||
auto bounds = draw_chunk($window, |
|
||||||
$text_bounds, $ui_text, |
|
||||||
default_bg, cur_bg, $config.bg_box_offset, x, y, out); |
|
||||||
x += bounds.size.x; |
|
||||||
} |
|
||||||
cur_bg = bg; |
|
||||||
$ui_text.setFillColor(fg); |
|
||||||
}, |
|
||||||
[&](wchar_t tile) { |
|
||||||
switch(tile) { |
|
||||||
case '\r': break; // ignore it
|
|
||||||
case '\n': { |
|
||||||
sf::FloatRect bounds; |
|
||||||
|
|
||||||
if(out.size() > 0) { |
|
||||||
bounds = draw_chunk($window, $text_bounds, |
|
||||||
$ui_text, default_bg, cur_bg, $config.bg_box_offset, x, y, out); |
|
||||||
} else { |
|
||||||
bounds = $ui_text.getLocalBounds(); |
|
||||||
} |
|
||||||
|
|
||||||
y += bounds.size.y; |
|
||||||
x = start_x; // reset to the original position
|
|
||||||
} |
|
||||||
break; |
|
||||||
default: |
|
||||||
out += tile; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
); |
|
||||||
|
|
||||||
if(out.size() > 0) { |
|
||||||
draw_chunk($window, $text_bounds, $ui_text, default_bg, cur_bg, $config.bg_box_offset, x, y, out); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void SFMLRender::draw_sprite(sf::Sprite &sprite, sf::Shader *shader) { |
|
||||||
$window.draw(sprite, shader); |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* Does not render the panel, you have to do that so you can control |
|
||||||
* when things render. |
|
||||||
*/ |
|
||||||
void SFMLRender::draw(Panel &panel, float x_offset, float y_offset) { |
|
||||||
const std::wstring &panelout = panel.to_string(); |
|
||||||
|
|
||||||
auto bounds = panel.grid ? $grid_bounds : $text_bounds; |
|
||||||
|
|
||||||
sf::RectangleShape backing( |
|
||||||
sf::Vector2f(bounds.size.x * panel.width + panel.border_px, |
|
||||||
bounds.size.y * panel.height + panel.border_px)); |
|
||||||
|
|
||||||
backing.setFillColor(panel.default_bg); |
|
||||||
|
|
||||||
if(panel.has_border) { |
|
||||||
backing.setOutlineColor(panel.border_color); |
|
||||||
backing.setOutlineThickness(panel.border_px); |
|
||||||
} |
|
||||||
|
|
||||||
backing.setPosition({panel.x + x_offset, panel.y + y_offset}); |
|
||||||
$window.draw(backing); |
|
||||||
|
|
||||||
if(panel.grid) { |
|
||||||
render_grid(panelout, panel.default_fg, panel.default_bg, panel.x + x_offset, panel.y + y_offset); |
|
||||||
} else { |
|
||||||
render_text(panelout, panel.default_fg, panel.default_bg, panel.x + x_offset, panel.y + y_offset); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
bool SFMLRender::mouse_position(Panel &panel, Point &out) { |
|
||||||
// yes, you have to do this in sfml
|
|
||||||
sf::Vector2f pos = $window.mapPixelToCoords(sf::Mouse::getPosition($window)); |
|
||||||
|
|
||||||
auto bounds = panel.grid ? $grid_bounds : $text_bounds; |
|
||||||
|
|
||||||
if(pos.x >= panel.x && pos.y >= panel.y |
|
||||||
&& pos.x <= (panel.x + panel.width * bounds.size.x) |
|
||||||
&& pos.y <= (panel.y + panel.height * bounds.size.y)) |
|
||||||
{ |
|
||||||
out = { |
|
||||||
size_t((pos.x - panel.x) / bounds.size.x), |
|
||||||
size_t((pos.y - panel.y) / bounds.size.y) |
|
||||||
}; |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
void SFMLRender::init_terminal() { |
|
||||||
#if defined(_WIN64) || defined(_WIN32) |
|
||||||
_setmode(_fileno(stdout), _O_U16TEXT); |
|
||||||
#endif |
|
||||||
|
|
||||||
ftxui::Terminal::SetColorSupport(ftxui::Terminal::Color::TrueColor); |
|
||||||
} |
|
@ -1,80 +0,0 @@ |
|||||||
#pragma once |
|
||||||
|
|
||||||
#include <ftxui/screen/screen.hpp> |
|
||||||
#include <ftxui/dom/canvas.hpp> |
|
||||||
#include <SFML/Window.hpp> |
|
||||||
#include <SFML/System.hpp> |
|
||||||
#include <SFML/Graphics.hpp> |
|
||||||
#include <SFML/Graphics/Rect.hpp> |
|
||||||
#include "point.hpp" |
|
||||||
#include <codecvt> |
|
||||||
#include "ansi_parser.hpp" |
|
||||||
#include "panel.hpp" |
|
||||||
#include "constants.hpp" |
|
||||||
#include <optional> |
|
||||||
|
|
||||||
using ftxui::Canvas, ftxui::Screen; |
|
||||||
|
|
||||||
/*
|
|
||||||
* BUG: This could be so much better. |
|
||||||
*/ |
|
||||||
struct RenderConfig { |
|
||||||
unsigned int video_x = SCREEN_WIDTH; |
|
||||||
unsigned int video_y = SCREEN_HEIGHT; |
|
||||||
int ui_font_size=UI_FONT_SIZE; |
|
||||||
int base_map_font_size=BASE_MAP_FONT_SIZE; |
|
||||||
wchar_t bg_tile = BG_TILE; |
|
||||||
wchar_t ui_base_char = UI_BASE_CHAR; |
|
||||||
int bg_box_offset=BG_BOX_OFFSET; |
|
||||||
}; |
|
||||||
|
|
||||||
struct SFMLRender { |
|
||||||
int $cells_w = 0; |
|
||||||
int $cells_h = 0; |
|
||||||
RenderConfig $config; |
|
||||||
sf::RenderWindow& $window; |
|
||||||
int $map_font_size; |
|
||||||
float $line_spacing; |
|
||||||
sf::Color $default_fg; |
|
||||||
sf::Color $default_bg; |
|
||||||
sf::Texture $font_texture; |
|
||||||
sf::Sprite $bg_sprite; |
|
||||||
sf::Font $font; |
|
||||||
sf::Text $ui_text; |
|
||||||
ANSIParser $ansi; |
|
||||||
|
|
||||||
std::unordered_map<wchar_t, sf::Sprite> $sprites; |
|
||||||
sf::Glyph $base_glyph; |
|
||||||
sf::FloatRect $grid_bounds; |
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> $converter; |
|
||||||
sf::FloatRect $text_bounds; |
|
||||||
|
|
||||||
SFMLRender(sf::RenderWindow& window); |
|
||||||
|
|
||||||
// disable copy
|
|
||||||
SFMLRender(SFMLRender &other) = delete; |
|
||||||
|
|
||||||
sf::Sprite &get_text_sprite(wchar_t tile); |
|
||||||
void resize_grid(int new_size, Panel &panel_out); |
|
||||||
void render_grid(const std::wstring &text, sf::Color default_fg, sf::Color default_bg, float x, float y); |
|
||||||
void render_text(const std::wstring &text, sf::Color default_fg, sf::Color default_bg, float x, float y); |
|
||||||
|
|
||||||
void draw(Panel &panel, float x_offset=0.0f, float y_offset=0.0f); |
|
||||||
void draw_sprite(sf::Sprite &sprite, sf::Shader *shader); |
|
||||||
void center_panel(Panel &panel); |
|
||||||
|
|
||||||
std::optional<sf::Event> poll_event() { |
|
||||||
return $window.pollEvent(); |
|
||||||
} |
|
||||||
|
|
||||||
void close() { return $window.close(); } |
|
||||||
|
|
||||||
bool is_open() { return $window.isOpen(); } |
|
||||||
|
|
||||||
int font_size() { return $map_font_size; } |
|
||||||
void clear() { $window.clear(); } |
|
||||||
void display() { $window.display(); } |
|
||||||
bool mouse_position(Panel &panel, Point &out); |
|
||||||
void clear_cache(); |
|
||||||
static void init_terminal(); |
|
||||||
}; |
|
@ -0,0 +1,17 @@ |
|||||||
|
#include <catch2/catch_test_macros.hpp> |
||||||
|
#include "easings.hpp" |
||||||
|
#include <cmath> |
||||||
|
|
||||||
|
TEST_CASE("make sure the easing functions at least run", "[easings]") { |
||||||
|
double out = ease::sine(1.3); |
||||||
|
REQUIRE(out <= 1.0); |
||||||
|
|
||||||
|
out = ease::out_circ(3.444); |
||||||
|
REQUIRE(std::isnan(out)); |
||||||
|
|
||||||
|
out = ease::out_bounce(1.13); |
||||||
|
REQUIRE(out <= 10 ); |
||||||
|
|
||||||
|
out = ease::in_out_back(3.4); |
||||||
|
REQUIRE(out < 250.0); |
||||||
|
} |
@ -1,15 +0,0 @@ |
|||||||
[wrap-file] |
|
||||||
directory = FTXUI-5.0.0 |
|
||||||
source_url = https://github.com/ArthurSonzogni/FTXUI/archive/refs/tags/v5.0.0.tar.gz |
|
||||||
source_filename = FTXUI-5.0.0.tar.gz |
|
||||||
source_hash = a2991cb222c944aee14397965d9f6b050245da849d8c5da7c72d112de2786b5b |
|
||||||
patch_filename = ftxui_5.0.0-1_patch.zip |
|
||||||
patch_url = https://wrapdb.mesonbuild.com/v2/ftxui_5.0.0-1/get_patch |
|
||||||
patch_hash = 21c654e82739b90b95bd98c1d321264608d37c50d29fbcc3487f790fd5412909 |
|
||||||
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/ftxui_5.0.0-1/FTXUI-5.0.0.tar.gz |
|
||||||
wrapdb_version = 5.0.0-1 |
|
||||||
|
|
||||||
[provide] |
|
||||||
ftxui-screen = screen_dep |
|
||||||
ftxui-dom = dom_dep |
|
||||||
ftxui-component = component_dep |
|
Loading…
Reference in new issue