2025-01-04 08:40:31 +01:00
// Written by retoor@molodetz.nl
2025-01-27 19:06:59 +01:00
// This program provides functionality to highlight the keywords in source code using ANSI color formatting and convert Markdown syntax into ANSI-colored text output.
2025-01-04 08:40:31 +01:00
// Uses standard C libraries: <stdio.h>, <string.h>. Also utilizes ANSI escape codes for text formatting.
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
2025-01-04 06:00:03 +01:00
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define RESET "\033[0m"
#define BOLD "\033[1m"
#define ITALIC "\033[3m"
#define FG_YELLOW "\033[33m"
#define FG_BLUE "\033[34m"
#define FG_CYAN "\033[36m"
int is_keyword ( const char * word ) {
const char * keywords [] = { "int" , "float" , "double" , "char" , "void" , "if" , "else" , "while" , "for" , "return" , "struct" , "printf" };
for ( size_t i = 0 ; i < sizeof ( keywords ) / sizeof ( keywords [ 0 ]); i ++ ) {
if ( strcmp ( word , keywords [ i ]) == 0 ) {
return 1 ;
}
}
return 0 ;
}
void highlight_code ( const char * code ) {
const char * ptr = code ;
2025-01-25 14:19:01 +01:00
char buffer [ 4096 ];
2025-01-04 06:00:03 +01:00
size_t index = 0 ;
2025-03-03 17:06:05 +01:00
2025-01-04 06:00:03 +01:00
while ( * ptr ) {
if (( * ptr >= 'a' && * ptr <= 'z' ) || ( * ptr >= 'A' && * ptr <= 'Z' ) || ( * ptr == '_' )) {
while (( * ptr >= 'a' && * ptr <= 'z' ) || ( * ptr >= 'A' && * ptr <= 'Z' ) || ( * ptr >= '0' && * ptr <= '9' ) || ( * ptr == '_' )) {
buffer [ index ++ ] = * ptr ++ ;
}
2025-01-25 14:19:01 +01:00
buffer [ index ] = 0 ;
2025-01-04 06:00:03 +01:00
if ( is_keyword ( buffer )) {
printf ( FG_BLUE "%s" RESET , buffer );
} else {
printf ( "%s" , buffer );
}
index = 0 ;
} else if ( * ptr >= '0' && * ptr <= '9' ) {
while ( * ptr >= '0' && * ptr <= '9' ) {
buffer [ index ++ ] = * ptr ++ ;
}
2025-01-25 14:19:01 +01:00
buffer [ index ] = 0 ;
2025-01-04 06:00:03 +01:00
printf ( FG_CYAN "%s" RESET , buffer );
index = 0 ;
} else {
putchar ( * ptr );
ptr ++ ;
}
}
}
void parse_markdown_to_ansi ( const char * markdown ) {
const char * ptr = markdown ;
bool inside_code = false ;
while ( * ptr ) {
if ( * ptr == '`' ) {
inside_code = ! inside_code ;
if ( inside_code ) {
printf ( FG_YELLOW );
} else {
printf ( RESET );
}
ptr ++ ;
continue ;
}
if ( inside_code ) {
2025-01-25 14:19:01 +01:00
char code_buffer [ 4096 ];
2025-01-04 06:00:03 +01:00
size_t index = 0 ;
while ( * ptr && * ptr != '`' ) {
code_buffer [ index ++ ] = * ptr ++ ;
2025-01-27 19:06:59 +01:00
if ( * ptr == '\n' || * ptr == ' ' || * ptr == '\t' || * ptr == '.' ) {
2025-01-25 14:19:01 +01:00
code_buffer [ index ++ ] = 0 ;
highlight_code ( code_buffer );
index = 0 ;
}
2025-01-04 06:00:03 +01:00
}
2025-01-26 02:54:45 +01:00
code_buffer [ index ] = 0 ;
2025-01-27 19:06:59 +01:00
if ( index ) {
2025-01-26 02:54:45 +01:00
highlight_code ( code_buffer );
2025-01-27 19:06:59 +01:00
}
2025-01-04 06:00:03 +01:00
} else {
if ( strncmp ( ptr , "**" , 2 ) == 0 ) {
printf ( BOLD );
ptr += 2 ;
2025-03-03 17:06:05 +01:00
while ( * ptr && strncmp ( ptr , "**" , 2 ) != 0 ) {
putchar ( * ptr ++ );
}
2025-01-04 06:00:03 +01:00
if ( * ptr == '*' && * ( ptr + 1 ) == '*' ) ptr += 2 ;
printf ( RESET );
2025-01-27 19:06:59 +01:00
} else if ( * ptr == '*' && ( ptr == markdown || * ( ptr - 1 ) != '*' )) {
2025-01-04 06:00:03 +01:00
printf ( ITALIC );
ptr ++ ;
2025-03-03 17:06:05 +01:00
while ( * ptr && * ptr != '*' ) {
putchar ( * ptr ++ );
}
2025-01-04 06:00:03 +01:00
if ( * ptr == '*' ) ptr ++ ;
printf ( RESET );
2025-01-27 19:06:59 +01:00
} else if ( strncmp ( ptr , "### " , 4 ) == 0 ) {
2025-01-04 06:00:03 +01:00
printf ( BOLD FG_YELLOW );
ptr += 4 ;
2025-03-03 17:06:05 +01:00
while ( * ptr && * ptr != '\n' ) {
putchar ( * ptr ++ );
}
2025-01-04 06:00:03 +01:00
printf ( RESET " \n " );
} else if ( strncmp ( ptr , "## " , 3 ) == 0 ) {
printf ( BOLD FG_YELLOW );
ptr += 3 ;
2025-03-03 17:06:05 +01:00
while ( * ptr && * ptr != '\n' ) {
putchar ( * ptr ++ );
}
2025-01-04 06:00:03 +01:00
printf ( RESET " \n " );
} else if ( strncmp ( ptr , "# " , 2 ) == 0 ) {
printf ( BOLD FG_YELLOW );
ptr += 2 ;
2025-03-03 17:06:05 +01:00
while ( * ptr && * ptr != '\n' ) {
putchar ( * ptr ++ );
}
2025-01-04 06:00:03 +01:00
printf ( RESET " \n " );
} else {
putchar ( * ptr );
ptr ++ ;
}
}
}
2025-01-27 19:06:59 +01:00
}