// Written by retoor@molodetz.nl // This program provides functionality to highlight the keywords in source code // using ANSI color formatting and convert Markdown syntax into ANSI-colored // text output. // Uses standard C libraries: , . 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. #include #include #include #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", // Rust keywords "let", "fn", "impl", "match", "enum", "trait", "use", "mod", "pub", "const", "static", // Python keywords "def", "class", "import", "from", "as", "with", "try", "except", "finally", "lambda", "async", "await", // Java keywords "public", "private", "protected", "class", "interface", "extends", "implements", "new", "static", "final", "synchronized", // JavaScript keywords "var", "let", "const", "function", "async", "await", "if", "else", "switch", "case", "break", "continue", "return", // C++ keywords "namespace", "template", "typename", "class", "public", "private", "protected", "virtual", "override", "friend", "new", // Go keywords "package", "import", "func", "var", "const", "type", "interface", "struct", "go", "defer", "select", // Bash keywords "if", "then", "else", "elif", "fi", "case", "esac", "for", "while", "until", "do", "done", "function", // C# keywords "namespace", "using", "class", "interface", "public", "private", "protected", "static", "void", "new", "override"}; 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; char buffer[4096]; size_t index = 0; 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++; } buffer[index] = 0; 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++; } buffer[index] = 0; 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 == '`' && *(ptr + 1) != '`') { inside_code = !inside_code; if (inside_code) { printf(FG_YELLOW); } else { printf(RESET); } ptr++; continue; } else if (!strncmp(ptr, "```", 3)) { inside_code = !inside_code; if (inside_code) { ptr = strstr(ptr, "\n") + 1; } else { ptr += 3; } if (*ptr == '\0') { break; } } if (inside_code) { char code_buffer[1024 * 1024] = {0}; ; size_t index = 0; while (*ptr && *ptr != '`') { code_buffer[index++] = *ptr++; if (*ptr == '\n' || *ptr == ' ' || *ptr == '\t' || *ptr == '.') { code_buffer[index++] = 0; highlight_code(code_buffer); index = 0; } } code_buffer[index] = 0; if (index) { highlight_code(code_buffer); } } else { if (strncmp(ptr, "**", 2) == 0) { printf(BOLD); ptr += 2; while (*ptr && strncmp(ptr, "**", 2) != 0) { putchar(*ptr++); } if (*ptr == '*' && *(ptr + 1) == '*') ptr += 2; printf(RESET); } else if (*ptr == '*' && (ptr == markdown || *(ptr - 1) != '*')) { printf(ITALIC); ptr++; while (*ptr && *ptr != '*') { putchar(*ptr++); } if (*ptr == '*') ptr++; printf(RESET); } else if (strncmp(ptr, "### ", 4) == 0) { printf(BOLD FG_YELLOW); ptr += 4; while (*ptr && *ptr != '\n') { putchar(*ptr++); } printf(RESET "\n"); } else if (strncmp(ptr, "## ", 3) == 0) { printf(BOLD FG_YELLOW); ptr += 3; while (*ptr && *ptr != '\n') { putchar(*ptr++); } printf(RESET "\n"); } else if (strncmp(ptr, "# ", 2) == 0) { printf(BOLD FG_YELLOW); ptr += 2; while (*ptr && *ptr != '\n') { putchar(*ptr++); } printf(RESET "\n"); } else { putchar(*ptr); ptr++; } } } }