Skip to content

Instantly share code, notes, and snippets.

@yne
Last active August 18, 2024 15:46
Show Gist options
  • Save yne/239aafaccbcb75108e3577277dd0984e to your computer and use it in GitHub Desktop.
Save yne/239aafaccbcb75108e3577277dd0984e to your computer and use it in GitHub Desktop.
DOM for TTY
#include <stdio.h>
#include <stdint.h>
#include <termios.h>
#define LEN(ARR) ARR,sizeof(ARR)/sizeof(*ARR)
#define RGBA(R,G,B,A) ((R<<24) | (G<<16) | (B<<8) | A)
#define RGB(R,G,B) RGBA(R,G,B,255)
typedef enum{
RULE_NOP,
RULE_TEXT_COLOR,
RULE_BACK_COLOR,
RULE_DISPLAY,
RULE_DISPLAY_INLINE,
RULE_DISPLAY_BLOCK,
RULE_TEXT_DECORATION,
RULE_TEXT_DECORATION_UNDERSCORE,
RULE_TEXT_DECORATION_BOLD,
}RuleOp;
typedef struct Rule{
RuleOp op:32;
uint32_t val;
}Rule;
typedef struct Node{
char*tag;
struct Node*nodes;size_t nodes_len;
struct Rule*rules;size_t rules_len;
char*url,*text;
struct Node*parent;
}Node;
/*
tag is predefined set of shorthand (a = take url and use ), example :
"a" tag will auto-define .onclick(LOAD,ATTR_URL,"app"),.target=app
"input" will have white bg and black text
so you don't have to specify can have lightweight definition
*/
Node app =
{"app",LEN(((Node[]){//on{resize,scroll(X/Y)}
{"menu",LEN(((Node[]){
{"a", LEN(((Node[]){})), LEN(((Rule[]){{RULE_TEXT_COLOR,RGB(0,255,0)}})), url:"http://test", text:"Home"},
{"a", LEN(((Node[]){})), LEN(((Rule[]){{RULE_TEXT_COLOR,RGB(0,0,255)}})), url:"http://test", text:"Download"},
{"a", LEN(((Node[]){})), LEN(((Rule[]){{RULE_TEXT_DECORATION,RULE_TEXT_DECORATION_BOLD}})), url:"http://test", text:"About"},
})), LEN(((Rule[]){{RULE_BACK_COLOR,RGB(128,0,0)},{RULE_TEXT_DECORATION,RULE_TEXT_DECORATION_UNDERSCORE},{RULE_DISPLAY,RULE_DISPLAY_INLINE}}))},
{"article",LEN(((Node[]){})), LEN(((Rule[]){})), text:"This is the interesting part of the document"}
})),LEN(((Rule[]){{RULE_TEXT_COLOR,RGB(0,0,0)}, {RULE_BACK_COLOR,RGB(255,255,255)}}))};
uint32_t*getRuleValue(Node*root,RuleOp op){
for(Rule*r = root->rules;r && r < root->rules+root->rules_len;r++)
if(r->op == op)
return &r->val;
return NULL;
}
uint32_t getInheritValue(Node*root,RuleOp op){
for(;root;root = root->parent){
uint32_t* value = getRuleValue(root,op);
if(value)
return *value;
}
return 0;
}
static struct termios old;
void init() {
tcgetattr(0, &old);
struct termios new = old;
new.c_lflag &= ~ICANON;
new.c_lflag &= ~ECHO;
tcsetattr(0, TCSANOW, &new);
}
void fini(void) {
tcsetattr(0, TCSANOW, &old);
printf("bye bye\n");
}
void draw(Node*root){
int depth = 0;
for(Node*n = root;n->parent;n=n->parent)depth++;
if(!root->parent)printf("\e[2J\e[0;0H");
uint32_t text = getInheritValue(root,RULE_TEXT_COLOR);
uint32_t back = getInheritValue(root,RULE_BACK_COLOR);
uint32_t deco = getInheritValue(root,RULE_TEXT_DECORATION);
uint32_t disp = getInheritValue(root,RULE_DISPLAY);
printf("\e[38;2;%i;%i;%im",text>>24,(text>>16)&0xFF,text&0xFF);
printf("\e[48;2;%i;%i;%im",back>>24,(back>>16)&0xFF,back&0xFF);
printf(deco&RULE_TEXT_DECORATION_UNDERSCORE?"\e[4m":"");
printf(deco&RULE_TEXT_DECORATION_BOLD?"\e[1m":"");
printf("%s",disp&RULE_DISPLAY_INLINE?"":"\n");
printf("%s\e[0m", root->text?:"");
printf("%s",disp&RULE_DISPLAY_INLINE?"":"\n");
for(Node*n = root->nodes;n && n < root->nodes+root->nodes_len;n++)
draw(n);
}
void build(Node*root){
for(Node*n = root->nodes;n && n < root->nodes+root->nodes_len;n++){
n->parent=root;
build(n);
}
}
void hydrate(Node*root){
if(!root->parent){
//TODO add default BACK/TEXT
}
for(Node*n = root->nodes;n && n < root->nodes+root->nodes_len;n++){
}
}
int main(){
init();
for(;;){
build(&app);
hydrate(&app);
draw(&app);
int c = getchar();
printf("%i ",c);
if(c==113)break;//q
}
fini();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment