163 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Ragel
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Ragel
		
	
	
	
	
	
| #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 = NULL;
 | |
|   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]));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return good;
 | |
| }
 | 
