Renderer of ANSI codes to SFML is now working. Does seem to be a little slow but that'll be easy to fix later.

main
Zed A. Shaw 3 weeks ago
parent ae484bf425
commit a36b187879
  1. 9
      Makefile
  2. 87
      ansi_parser.cpp
  3. 4
      ansi_parser.hpp
  4. 32
      ansi_parser.rl
  5. 6
      map.hpp
  6. 8
      meson.build
  7. 4
      render.cpp
  8. 8
      tests/ansi_parser.cpp

@ -3,16 +3,17 @@ all: build test
reset: reset:
powershell -executionpolicy bypass .\scripts\reset_build.ps1 powershell -executionpolicy bypass .\scripts\reset_build.ps1
rageldev: %.cpp : %.rl
make ragel ragel -o $@ $<
rageldev: ragel
make test > test.txt make test > test.txt
vim test.txt vim test.txt
ragel: ragel:
ragel -o .\scratchpad\testragel.cpp .\scratchpad\testragel.rl
ragel -o .\ansi_parser.cpp .\ansi_parser.rl ragel -o .\ansi_parser.cpp .\ansi_parser.rl
build: build: ansi_parser.cpp
meson compile -j 4 -C builddir meson compile -j 4 -C builddir
test: build test: build

@ -10,7 +10,7 @@
using namespace fmt; using namespace fmt;
#line 59 ".\\ansi_parser.rl" #line 77 ".\\ansi_parser.rl"
@ -28,7 +28,7 @@ static const char _foo_key_offsets[] = {
27, 28, 29, 30, 31 27, 28, 29, 30, 31
}; };
static const char _foo_trans_keys[] = { static const int _foo_trans_keys[] = {
27, 91, 51, 52, 56, 57, 59, 50, 27, 91, 51, 52, 56, 57, 59, 50,
59, 48, 57, 59, 48, 57, 48, 57, 59, 48, 57, 59, 48, 57, 48, 57,
59, 48, 57, 48, 57, 109, 48, 57, 59, 48, 57, 48, 57, 109, 48, 57,
@ -85,15 +85,15 @@ static const int foo_error = 0;
static const int foo_en_main = 19; static const int foo_en_main = 19;
#line 62 ".\\ansi_parser.rl" #line 80 ".\\ansi_parser.rl"
bool parse_ansi(std::string_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write) { bool parse_ansi(std::wstring_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write) {
const char *start = NULL; const wchar_t *start = NULL;
int cs = 0; int cs = 0;
unsigned int value = 0; unsigned int value = 0;
const char *p = codes.data(); const wchar_t *p = codes.data();
const char *pe = p + codes.size(); const wchar_t *pe = p + codes.size();
const char *eof = pe; const wchar_t *eof = pe;
sf::Color bgcolor(default_bg); sf::Color bgcolor(default_bg);
sf::Color color(default_fg); sf::Color color(default_fg);
sf::Color &target = bgcolor; sf::Color &target = bgcolor;
@ -104,7 +104,7 @@ bool parse_ansi(std::string_view codes, sf::Color default_fg, sf::Color default_
cs = foo_start; cs = foo_start;
} }
#line 75 ".\\ansi_parser.rl" #line 93 ".\\ansi_parser.rl"
#line 97 ".\\ansi_parser.cpp" #line 97 ".\\ansi_parser.cpp"
{ {
@ -112,7 +112,7 @@ bool parse_ansi(std::string_view codes, sf::Color default_fg, sf::Color default_
unsigned int _trans; unsigned int _trans;
const char *_acts; const char *_acts;
unsigned int _nacts; unsigned int _nacts;
const char *_keys; const int *_keys;
if ( p == pe ) if ( p == pe )
goto _test_eof; goto _test_eof;
@ -124,9 +124,9 @@ _resume:
_klen = _foo_single_lengths[cs]; _klen = _foo_single_lengths[cs];
if ( _klen > 0 ) { if ( _klen > 0 ) {
const char *_lower = _keys; const int *_lower = _keys;
const char *_mid; const int *_mid;
const char *_upper = _keys + _klen - 1; const int *_upper = _keys + _klen - 1;
while (1) { while (1) {
if ( _upper < _lower ) if ( _upper < _lower )
break; break;
@ -147,9 +147,9 @@ _resume:
_klen = _foo_range_lengths[cs]; _klen = _foo_range_lengths[cs];
if ( _klen > 0 ) { if ( _klen > 0 ) {
const char *_lower = _keys; const int *_lower = _keys;
const char *_mid; const int *_mid;
const char *_upper = _keys + (_klen<<1) - 2; const int *_upper = _keys + (_klen<<1) - 2;
while (1) { while (1) {
if ( _upper < _lower ) if ( _upper < _lower )
break; break;
@ -180,65 +180,82 @@ _match:
switch ( *_acts++ ) switch ( *_acts++ )
{ {
case 0: case 0:
#line 13 ".\\ansi_parser.rl" #line 14 ".\\ansi_parser.rl"
{ {
start = p; start = p;
} }
break; break;
case 1: case 1:
#line 17 ".\\ansi_parser.rl" #line 18 ".\\ansi_parser.rl"
{ {
auto [ptr, ec] = std::from_chars(start, p, value); value = 0;
dbc::check(ec == std::errc(), "error in number parsing"); size_t len = p - start;
dbc::check(start[0] != '-', "negative numbers not supported");
switch(len) {
case 10: value += (start[len-10] - '0') * 1000000000;
case 9: value += (start[len- 9] - '0') * 100000000;
case 8: value += (start[len- 8] - '0') * 10000000;
case 7: value += (start[len- 7] - '0') * 1000000;
case 6: value += (start[len- 6] - '0') * 100000;
case 5: value += (start[len- 5] - '0') * 10000;
case 4: value += (start[len- 4] - '0') * 1000;
case 3: value += (start[len- 3] - '0') * 100;
case 2: value += (start[len- 2] - '0') * 10;
case 1: value += (start[len- 1] - '0');
break;
default:
dbc::sentinel("can't process > 10 digits");
}
} }
break; break;
case 2: case 2:
#line 22 ".\\ansi_parser.rl" #line 40 ".\\ansi_parser.rl"
{ } { }
break; break;
case 3: case 3:
#line 23 ".\\ansi_parser.rl" #line 41 ".\\ansi_parser.rl"
{ target = color; } { target = color; }
break; break;
case 4: case 4:
#line 24 ".\\ansi_parser.rl" #line 42 ".\\ansi_parser.rl"
{ target = bgcolor; } { target = bgcolor; }
break; break;
case 5: case 5:
#line 26 ".\\ansi_parser.rl" #line 44 ".\\ansi_parser.rl"
{ {
write(bgcolor, color, (*p)); write(bgcolor, color, (*p));
} }
break; break;
case 6: case 6:
#line 30 ".\\ansi_parser.rl" #line 48 ".\\ansi_parser.rl"
{ color = default_fg; } { color = default_fg; }
break; break;
case 7: case 7:
#line 31 ".\\ansi_parser.rl" #line 49 ".\\ansi_parser.rl"
{ bgcolor = default_bg; } { bgcolor = default_bg; }
break; break;
case 8: case 8:
#line 33 ".\\ansi_parser.rl" #line 51 ".\\ansi_parser.rl"
{ target.r = value; } { target.r = value; }
break; break;
case 9: case 9:
#line 34 ".\\ansi_parser.rl" #line 52 ".\\ansi_parser.rl"
{ target.g = value; } { target.g = value; }
break; break;
case 10: case 10:
#line 35 ".\\ansi_parser.rl" #line 53 ".\\ansi_parser.rl"
{ target.b = value; } { target.b = value; }
break; break;
case 11: case 11:
#line 36 ".\\ansi_parser.rl" #line 54 ".\\ansi_parser.rl"
{ value = 0; } { value = 0; }
break; break;
case 12: case 12:
#line 37 ".\\ansi_parser.rl" #line 55 ".\\ansi_parser.rl"
{ } { }
break; break;
#line 215 ".\\ansi_parser.cpp" #line 232 ".\\ansi_parser.cpp"
} }
} }
@ -255,10 +272,10 @@ _again:
while ( __nacts-- > 0 ) { while ( __nacts-- > 0 ) {
switch ( *__acts++ ) { switch ( *__acts++ ) {
case 12: case 12:
#line 37 ".\\ansi_parser.rl" #line 55 ".\\ansi_parser.rl"
{ } { }
break; break;
#line 233 ".\\ansi_parser.cpp" #line 250 ".\\ansi_parser.cpp"
} }
} }
} }
@ -266,7 +283,7 @@ _again:
_out: {} _out: {}
} }
#line 76 ".\\ansi_parser.rl" #line 94 ".\\ansi_parser.rl"
return p - pe == 0; return p - pe == 0;
} }

@ -2,6 +2,6 @@
#include <string_view> #include <string_view>
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
typedef std::function<void(sf::Color bgcolor, sf::Color color, char ch)> WriteCB; typedef std::function<void(sf::Color bgcolor, sf::Color color, wchar_t ch)> WriteCB;
bool parse_ansi(std::string_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write); bool parse_ansi(std::wstring_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write);

@ -9,14 +9,32 @@ using namespace fmt;
%%{ %%{
machine foo; machine foo;
alphtype int;
action tstart { action tstart {
start = fpc; start = fpc;
} }
action number { action number {
auto [ptr, ec] = std::from_chars(start, fpc, value); value = 0;
dbc::check(ec == std::errc(), "error in number parsing"); size_t len = fpc - start;
dbc::check(start[0] != '-', "negative numbers not supported");
switch(len) {
case 10: value += (start[len-10] - '0') * 1000000000;
case 9: value += (start[len- 9] - '0') * 100000000;
case 8: value += (start[len- 8] - '0') * 10000000;
case 7: value += (start[len- 7] - '0') * 1000000;
case 6: value += (start[len- 6] - '0') * 100000;
case 5: value += (start[len- 5] - '0') * 10000;
case 4: value += (start[len- 4] - '0') * 1000;
case 3: value += (start[len- 3] - '0') * 100;
case 2: value += (start[len- 2] - '0') * 10;
case 1: value += (start[len- 1] - '0');
break;
default:
dbc::sentinel("can't process > 10 digits");
}
} }
action color24b { } action color24b { }
@ -60,13 +78,13 @@ using namespace fmt;
%% write data; %% write data;
bool parse_ansi(std::string_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write) { bool parse_ansi(std::wstring_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write) {
const char *start = NULL; const wchar_t *start = NULL;
int cs = 0; int cs = 0;
unsigned int value = 0; unsigned int value = 0;
const char *p = codes.data(); const wchar_t *p = codes.data();
const char *pe = p + codes.size(); const wchar_t *pe = p + codes.size();
const char *eof = pe; const wchar_t *eof = pe;
sf::Color bgcolor(default_bg); sf::Color bgcolor(default_bg);
sf::Color color(default_fg); sf::Color color(default_fg);
sf::Color &target = bgcolor; sf::Color &target = bgcolor;

@ -11,10 +11,10 @@
#define INV_SPACE 1 #define INV_SPACE 1
#define WALL_VALUE 1 #define WALL_VALUE 1
#define SPACE_VALUE 0 #define SPACE_VALUE 0
#define WALL_TILE "#" #define WALL_TILE ""
#define FLOOR_TILE "." #define FLOOR_TILE "."
#define PLAYER_TILE "&" #define PLAYER_TILE ""
#define ENEMY_TILE "!" #define ENEMY_TILE "Ω"
struct Room { struct Room {
size_t x = 0; size_t x = 0;

@ -20,7 +20,7 @@ runtests = executable('runtests', [
'sound.cpp', 'sound.cpp',
'collider.cpp', 'collider.cpp',
'ansi_parser.cpp', 'ansi_parser.cpp',
'render.cpp', #'render.cpp',
'tests/fsm.cpp', 'tests/fsm.cpp',
'tests/dbc.cpp', 'tests/dbc.cpp',
'tests/map.cpp', 'tests/map.cpp',
@ -51,10 +51,4 @@ collider = executable('collider', [
], ],
dependencies: dependencies) dependencies: dependencies)
testragel = executable('testragel', [
'dbc.cpp',
'./scratchpad/testragel.cpp'
],
dependencies: dependencies)
test('tests', runtests) test('tests', runtests)

@ -87,10 +87,10 @@ void SFMLRender::draw_screen(bool clear, float map_off_x, float map_off_y) {
// make a copy so we don't modify the cached one // make a copy so we don't modify the cached one
auto bg_sprite = get_text_sprite(L''); auto bg_sprite = get_text_sprite(L'');
auto bg_bounds = bg_sprite.getLocalBounds(); auto bg_bounds = bg_sprite.getLocalBounds();
sf::Color def_fg(color(Value::LIGHT_LIGHT)); sf::Color def_fg(color(Value::MID));
sf::Color def_bg(color(Value::BLACK)); sf::Color def_bg(color(Value::BLACK));
parse_ansi(map_screenout, def_fg, def_bg, [&](sf::Color bg, sf::Color fg, char tile) { parse_ansi(map_screen_utf8, def_fg, def_bg, [&](sf::Color bg, sf::Color fg, wchar_t tile) {
if(tile == '\n') { if(tile == '\n') {
// don't bother processing newlines, just skip // don't bother processing newlines, just skip
y += $line_spacing; y += $line_spacing;

@ -2,6 +2,7 @@
#include <fmt/core.h> #include <fmt/core.h>
#include <string> #include <string>
#include "ansi_parser.hpp" #include "ansi_parser.hpp"
#include <codecvt>
#include "ftxui/dom/elements.hpp" // for text, bgcolor, color, vbox, hbox, separator, operator|, Elements, Element, Fit, border #include "ftxui/dom/elements.hpp" // for text, bgcolor, color, vbox, hbox, separator, operator|, Elements, Element, Fit, border
@ -52,11 +53,14 @@ std::string generate_colors() {
TEST_CASE("test out ragel parser", "[gui]") { TEST_CASE("test out ragel parser", "[gui]") {
std::string colors = generate_colors(); std::string colors = generate_colors();
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring colors_utf8 = converter.from_bytes(colors);
sf::Color default_fg(0,0,0); sf::Color default_fg(0,0,0);
sf::Color default_bg(100,100,100); sf::Color default_bg(100,100,100);
println("--- PARSING"); bool good = parse_ansi(colors_utf8, default_fg, default_bg, [&](sf::Color bgcolor, sf::Color color, wchar_t ch) {
bool good = parse_ansi(colors, default_fg, default_bg, [&](sf::Color bgcolor, sf::Color color, char ch) {
bool correct_char = ch == '#' || ch == ' ' || ch == '\n' || ch == '\r'; bool correct_char = ch == '#' || ch == ' ' || ch == '\n' || ch == '\r';
// println("FG: {},{},{},{}; BG: {},{},{},{}; ch: {}", // println("FG: {},{},{},{}; BG: {},{},{},{}; ch: {}",
// color.r, color.g, color.b, color.a, // color.r, color.g, color.b, color.a,

Loading…
Cancel
Save