the code
This commit is contained in:
Executable
+336
@@ -0,0 +1,336 @@
|
|||||||
|
const MY_COLOR: u64 = 0x22223Bffffffu64;
|
||||||
|
const CARD_LEN: usize = 50;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct MdMapping {
|
||||||
|
pub md_start: &'static str,
|
||||||
|
pub md_end: &'static str,
|
||||||
|
pub html_start: &'static str,
|
||||||
|
pub html_end: &'static str,
|
||||||
|
pub ansi_start: &'static str,
|
||||||
|
pub ansi_end: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
static MD_MAP: &[MdMapping] = &[
|
||||||
|
MdMapping { md_start: "# ", md_end: "", html_start: "<h1>", html_end: "</h1>", ansi_start: "\x1b[1;37m", ansi_end: "\x1b[0m" },
|
||||||
|
MdMapping { md_start: "## ", md_end: "", html_start: "<h2>", html_end: "</h2>", ansi_start: "\x1b[1;36m", ansi_end: "\x1b[0m" },
|
||||||
|
MdMapping { md_start: "### ", md_end: "", html_start: "<h3>", html_end: "</h3>", ansi_start: "\x1b[1;35m", ansi_end: "\x1b[0m" },
|
||||||
|
MdMapping { md_start: "#### ", md_end: "", html_start: "<h4>", html_end: "</h4>", ansi_start: "\x1b[1;34m", ansi_end: "\x1b[0m" },
|
||||||
|
MdMapping { md_start: "##### ", md_end: "", html_start: "<h5>", html_end: "</h5>", ansi_start: "\x1b[1;33m", ansi_end: "\x1b[0m" },
|
||||||
|
MdMapping { md_start: "###### ", md_end: "", html_start: "<h6>", html_end: "</h6>", ansi_start: "\x1b[1;32m", ansi_end: "\x1b[0m" },
|
||||||
|
MdMapping { md_start: "**", md_end: "**", html_start: "<strong>", html_end: "</strong>", ansi_start: "\x1b[1m", ansi_end: "\x1b[0m" },
|
||||||
|
MdMapping { md_start: "__", md_end: "__", html_start: "<strong>", html_end: "</strong>", ansi_start: "\x1b[1m", ansi_end: "\x1b[0m" },
|
||||||
|
MdMapping { md_start: "*", md_end: "*", html_start: "<em>", html_end: "</em>", ansi_start: "\x1b[3m", ansi_end: "\x1b[0m" },
|
||||||
|
MdMapping { md_start: "_", md_end: "_", html_start: "<em>", html_end: "</em>", ansi_start: "\x1b[3m", ansi_end: "\x1b[0m" },
|
||||||
|
MdMapping { md_start: "~~", md_end: "~~", html_start: "<del>", html_end: "</del>", ansi_start: "\x1b[9m", ansi_end: "\x1b[0m" },
|
||||||
|
MdMapping { md_start: "`", md_end: "`", html_start: "<code>", html_end: "</code>", ansi_start: "\x1b[7m", ansi_end: "\x1b[0m" },
|
||||||
|
];
|
||||||
|
|
||||||
|
fn log(message: &str) {
|
||||||
|
println!("{}", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pp(res: &mut String, input: String) {
|
||||||
|
res.push_str(&input);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pri(res: &mut String, col: u64, text: &str) {
|
||||||
|
let bg_r = ((col >> 40) & 0xFF) as u8;
|
||||||
|
let bg_g = ((col >> 32) & 0xFF) as u8;
|
||||||
|
let bg_b = ((col >> 24) & 0xFF) as u8;
|
||||||
|
let fg_r = ((col >> 16) & 0xFF) as u8;
|
||||||
|
let fg_g = ((col >> 8) & 0xFF) as u8;
|
||||||
|
let fg_b = (col & 0xFF) as u8;
|
||||||
|
pp(res, format!("\x1b[38;2;{};{};{}m", fg_r, fg_g, fg_b));
|
||||||
|
pp(res, format!("\x1b[48;2;{};{};{}m", bg_r, bg_g, bg_b));
|
||||||
|
pp(res, format!("{}", text));
|
||||||
|
pp(res, format!("\x1b[0m"));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_line(res: &mut String) {
|
||||||
|
let first = format!(" {} ", "=".repeat(CARD_LEN));
|
||||||
|
res.push_str(&first);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_head(res: &mut String) {
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
let LL: String = String::from("\n");
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
let SS: String = String::from(" ");
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
let QQ: String = String::from(" | ");
|
||||||
|
pp(res, SS.clone());
|
||||||
|
pri(res, MY_COLOR, &format!("{: <50}", " "));
|
||||||
|
pp(res, QQ.clone());
|
||||||
|
pri(res, MY_COLOR, &format!("{: <50}", " "));
|
||||||
|
pp(res, QQ);
|
||||||
|
pri(res, MY_COLOR, &format!("{: <50}", " "));
|
||||||
|
pp(res, LL.clone());
|
||||||
|
draw_line(res);
|
||||||
|
pp(res, LL);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_table_ansi(res: &mut String, lines: &[&str]) {
|
||||||
|
print_head(res);
|
||||||
|
for (_idx, line) in lines.iter().enumerate() {
|
||||||
|
if line.starts_with('|') && line.contains("---") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let cells: Vec<&str> = line.split('|').collect();
|
||||||
|
for index in 1..cells.len() {
|
||||||
|
pri(res, MY_COLOR, &format!("{: <50}", process_inline(cells[index], true)));
|
||||||
|
res.push_str(" | ");
|
||||||
|
}
|
||||||
|
res.push_str("\n");
|
||||||
|
}
|
||||||
|
draw_line(res);
|
||||||
|
res.push_str("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_inline(text: &str, use_ansi: bool) -> String {
|
||||||
|
let mut result = text.to_string();
|
||||||
|
for m in MD_MAP {
|
||||||
|
if !m.md_end.is_empty() {
|
||||||
|
let placeholder = format!("{}{}{}", m.md_start, "{}", m.md_end);
|
||||||
|
let replacement = if use_ansi {
|
||||||
|
format!("{}{}{}", m.ansi_start, "{}", m.ansi_end)
|
||||||
|
} else {
|
||||||
|
format!("{}{}{}", m.html_start, "{}", m.html_end)
|
||||||
|
};
|
||||||
|
result = result.replace(&placeholder, &replacement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_heading(line: &str, use_ansi: bool) -> Option<String> {
|
||||||
|
for m in MD_MAP {
|
||||||
|
if line.starts_with(m.md_start) && m.md_end.is_empty() {
|
||||||
|
let content = line.trim_start_matches(m.md_start).trim();
|
||||||
|
let processed = process_inline(content, use_ansi);
|
||||||
|
if use_ansi {
|
||||||
|
return Some(format!(
|
||||||
|
"\x1b[48;2;0;0;0m\x1b[38;2;255;255;255m{}\x1b[0m",
|
||||||
|
processed
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
return Some(format!("{}{}{}", m.html_start, processed, m.html_end));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_list_item(line: &str) -> Option<(usize, bool, String)> {
|
||||||
|
log(&format!("Checking for list item: '{}'", line));
|
||||||
|
let trimmed = line.trim_start();
|
||||||
|
let indent = line.len() - trimmed.len();
|
||||||
|
if trimmed.starts_with("- ") || trimmed.starts_with("* ") || trimmed.starts_with("+ ") {
|
||||||
|
let content = trimmed[2..].trim().to_string();
|
||||||
|
log(&format!("Unordered list item found: '{}'", content));
|
||||||
|
return Some((indent, false, content));
|
||||||
|
}
|
||||||
|
if let Some(dot_pos) = trimmed.find(". ") {
|
||||||
|
if dot_pos > 0 && trimmed[0..dot_pos].chars().all(|c| c.is_numeric()) {
|
||||||
|
let content = trimmed[dot_pos + 2..].trim().to_string();
|
||||||
|
log(&format!("Ordered list item found: '{}'", content));
|
||||||
|
return Some((indent, true, content));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_horizontal_rule(line: &str) -> bool {
|
||||||
|
let trimmed = line.trim();
|
||||||
|
if trimmed.len() < 3 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
(trimmed.starts_with("---") && trimmed.chars().all(|c| c == '-' || c.is_whitespace())) ||
|
||||||
|
(trimmed.starts_with("***") && trimmed.chars().all(|c| c == '*' || c.is_whitespace())) ||
|
||||||
|
(trimmed.starts_with("___") && trimmed.chars().all(|c| c == '_' || c.is_whitespace()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_table(lines: &[&str]) -> String {
|
||||||
|
log(&format!("Processing table with {} rows", lines.len()));
|
||||||
|
let mut html = String::from("<table style=\"border-collapse: collapse; border: 1px solid #ccc; margin: 1em 0;\">\n");
|
||||||
|
for (i, line) in lines.iter().enumerate() {
|
||||||
|
if !line.trim().starts_with('|') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let cells: Vec<&str> = line.split('|')
|
||||||
|
.filter(|s| !s.trim().is_empty())
|
||||||
|
.map(|s| s.trim())
|
||||||
|
.collect();
|
||||||
|
if cells.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if i == 0 || line.contains("---") {
|
||||||
|
html.push_str("<thead><tr>");
|
||||||
|
for cell in &cells {
|
||||||
|
html.push_str(&format!("<th style=\"border: 1px solid #ccc; padding: 10px; text-align: left;\">{}</th>", process_inline(cell, false)));
|
||||||
|
}
|
||||||
|
html.push_str("</tr></thead>\n");
|
||||||
|
} else {
|
||||||
|
html.push_str("<tr>");
|
||||||
|
for cell in &cells {
|
||||||
|
html.push_str(&format!("<td style=\"border: 1px solid #ccc; padding: 10px;\">{}</td>", process_inline(cell, false)));
|
||||||
|
}
|
||||||
|
html.push_str("</tr>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html.push_str("</table>\n");
|
||||||
|
html
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_code_block(lines: &[&str], start_idx: &mut usize) -> String {
|
||||||
|
log("Code block detected");
|
||||||
|
let mut html = String::from("<pre><code>");
|
||||||
|
*start_idx += 1;
|
||||||
|
while *start_idx < lines.len() && !lines[*start_idx].starts_with("```") {
|
||||||
|
html.push_str(lines[*start_idx]);
|
||||||
|
html.push('\n');
|
||||||
|
*start_idx += 1;
|
||||||
|
}
|
||||||
|
html.push_str("</code></pre>\n");
|
||||||
|
*start_idx += 1;
|
||||||
|
html
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_list(lines: &[&str], start_idx: &mut usize) -> String {
|
||||||
|
log("Starting new list");
|
||||||
|
let mut html = String::from("<ul>\n");
|
||||||
|
while *start_idx < lines.len() {
|
||||||
|
if let Some((_, _, content)) = is_list_item(lines[*start_idx]) {
|
||||||
|
html.push_str(&format!(" <li>{}</li>\n", process_inline(&content, false)));
|
||||||
|
*start_idx += 1;
|
||||||
|
} else if lines[*start_idx].trim().is_empty() {
|
||||||
|
*start_idx += 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html.push_str("</ul>\n");
|
||||||
|
html
|
||||||
|
}
|
||||||
|
|
||||||
|
fn md_to_ansi(md_content: &str) -> String {
|
||||||
|
let mut output = String::new();
|
||||||
|
let lines: Vec<&str> = md_content.lines().collect();
|
||||||
|
let mut i = 0;
|
||||||
|
while i < lines.len() {
|
||||||
|
let line = lines[i];
|
||||||
|
if line.trim().starts_with('|') && i + 1 < lines.len() && lines[i + 1].contains("---") {
|
||||||
|
let mut table_lines = Vec::new();
|
||||||
|
while i < lines.len() && lines[i].trim().starts_with('|') {
|
||||||
|
table_lines.push(lines[i]);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
process_table_ansi(&mut output, &table_lines);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some(h) = process_heading(line, true) {
|
||||||
|
output.push_str(&h);
|
||||||
|
output.push('\n');
|
||||||
|
i += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let trimmed = line.trim_start();
|
||||||
|
if trimmed.starts_with("- ") || trimmed.starts_with("* ") || trimmed.starts_with("+ ") {
|
||||||
|
let content = trimmed[2..].trim();
|
||||||
|
output.push_str(&format!(" • {}\n", process_inline(content, true)));
|
||||||
|
i += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let processed = process_inline(line, true);
|
||||||
|
if !processed.trim().is_empty() {
|
||||||
|
output.push_str(&processed);
|
||||||
|
output.push('\n');
|
||||||
|
} else if line.trim().is_empty() {
|
||||||
|
output.push('\n');
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn md_to_html(md_content: &str) -> String {
|
||||||
|
log("Starting Markdown to HTML conversion");
|
||||||
|
let mut html = String::from(r#"
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Markdown Preview</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; max-width: 980px; margin: 40px auto; padding: 0 20px; line-height: 1.7; }
|
||||||
|
h1, h2, h3 { border-bottom: 1px solid #ddd; padding-bottom: 0.3em; }
|
||||||
|
ul, ol { padding-left: 2em; }
|
||||||
|
li { margin: 0.35em 0; }
|
||||||
|
table { border-collapse: collapse; margin: 1em 0; }
|
||||||
|
th, td { border: 1px solid #ccc; padding: 10px; }
|
||||||
|
pre { background: #f6f8fa; padding: 16px; overflow: auto; border-radius: 6px; }
|
||||||
|
code { background: #f6f8fa; padding: 0.2em 0.4em; border-radius: 3px; }
|
||||||
|
hr { border: 0; border-top: 3px double #333; margin: 2em 0; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="markdown-body">
|
||||||
|
"#);
|
||||||
|
let lines: Vec<&str> = md_content.lines().collect();
|
||||||
|
let mut i = 0;
|
||||||
|
while i < lines.len() {
|
||||||
|
let line = lines[i];
|
||||||
|
if is_horizontal_rule(line) {
|
||||||
|
html.push_str("<hr>\n");
|
||||||
|
i += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some(heading) = process_heading(line, false) {
|
||||||
|
html.push_str(&heading);
|
||||||
|
html.push('\n');
|
||||||
|
i += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if is_list_item(line).is_some() {
|
||||||
|
let list_html = process_list(&lines, &mut i);
|
||||||
|
html.push_str(&list_html);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if line.trim().starts_with('|') && i + 1 < lines.len() && lines[i + 1].contains("---") {
|
||||||
|
let mut table_lines = Vec::new();
|
||||||
|
while i < lines.len() && lines[i].trim().starts_with('|') {
|
||||||
|
table_lines.push(lines[i]);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
html.push_str(&process_table(&table_lines));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if line.starts_with("```") {
|
||||||
|
let code_html = process_code_block(&lines, &mut i);
|
||||||
|
html.push_str(&code_html);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let processed = process_inline(line, false);
|
||||||
|
if !processed.trim().is_empty() {
|
||||||
|
html.push_str(&processed);
|
||||||
|
html.push('\n');
|
||||||
|
} else if line.trim().is_empty() {
|
||||||
|
html.push_str("<br>\n");
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
html.push_str("</body></html>");
|
||||||
|
html
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn md_html_main(md_content: &str, output: &mut String) {
|
||||||
|
let html = md_to_html(md_content);
|
||||||
|
output.clear();
|
||||||
|
output.push_str(&html);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn md_ansi_main(md_content: &str, output: &mut String) {
|
||||||
|
let ansi = md_to_ansi(md_content);
|
||||||
|
output.clear();
|
||||||
|
output.push_str(&ansi);
|
||||||
|
}
|
||||||
|
|
||||||
Executable
+51
@@ -0,0 +1,51 @@
|
|||||||
|
#[derive(Clone)]
|
||||||
|
pub struct HighlightConfig {
|
||||||
|
pub color_keyword: &'static str,
|
||||||
|
pub color_string: &'static str,
|
||||||
|
pub color_comment: &'static str,
|
||||||
|
pub color_header: &'static str,
|
||||||
|
pub color_tag: &'static str,
|
||||||
|
pub color_numbers: &'static str,
|
||||||
|
pub color_reset: &'static str,
|
||||||
|
pub color_ip: &'static str,
|
||||||
|
pub color_timestamp: &'static str,
|
||||||
|
pub color_hex: &'static str,
|
||||||
|
pub new_line: &'static str
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HighlightConfig {
|
||||||
|
pub fn html_colors() -> Self {
|
||||||
|
Self {
|
||||||
|
color_keyword: "<span style='color: #0000DD; font-weight: bold;'>",
|
||||||
|
color_string: "<span style='color: #855500;'>",
|
||||||
|
color_comment: "<span style='color: #ffff00; font-style: italic;'>",
|
||||||
|
color_header: "<span style='color: #75803B;'>",
|
||||||
|
color_tag: "<span style='color: #A70022;'>",
|
||||||
|
color_numbers: "<span style='color: #ff0000;'>",
|
||||||
|
color_reset: "</span>",
|
||||||
|
color_hex: "<span style='color: #ff0000'>",
|
||||||
|
color_ip: "<span style='color: #ffff00'>",
|
||||||
|
color_timestamp: "<span style='color: #555555'>",
|
||||||
|
new_line: "<br>",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for HighlightConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
color_keyword: "\x1b[38;2;0;255;255m", // Neon-Cyan
|
||||||
|
color_string: "\x1b[38;2;255;255;85m", // Neon-Gelb
|
||||||
|
color_comment: "\x1b[38;2;180;180;180m", // Helles Grau
|
||||||
|
color_header: "\x1b[38;2;255;0;255m", // Knalliges Magenta
|
||||||
|
color_tag: "\x1b[38;2;255;85;85m", // Neon-Rot
|
||||||
|
color_numbers: "\x1b[38;2;255;0;0m", // Rot
|
||||||
|
color_reset: "\x1b[0m", // Reset
|
||||||
|
color_ip: "\x1b[38;2;0;170;255m", // Leuchtendes Blau
|
||||||
|
color_timestamp: "\x1b[38;2;200;100;255m", // Lila/Violett
|
||||||
|
color_hex: "\x1b[38;2;220;220;220m", // Helles Silber
|
||||||
|
new_line: "\n",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Regular → Executable
Executable
+278
@@ -0,0 +1,278 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use crate::keywords::{
|
||||||
|
ASM_8051_KEYWORDS, ASM_X86_KEYWORDS, KEYWORDS_C, DOCKER_KEYWORDS, JS_KEYWORDS,
|
||||||
|
PYTHON_KEYWORDS, RUST_KEYWORDS, SHELL_KEYWORDS, SQL_KEYWORDS, Keyword,
|
||||||
|
DOCKER_COMPOSE_KEYWORDS, JAVA_KEYWORDS
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::state::State;
|
||||||
|
use crate::language::Language;
|
||||||
|
use crate::col::HighlightConfig;
|
||||||
|
|
||||||
|
fn is_word_char(c: char) -> bool {
|
||||||
|
c.is_alphanumeric() || c == '_' || c == '$'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_keyword(word: &str, keywords: &[Keyword]) -> bool
|
||||||
|
{
|
||||||
|
keywords.iter().any(|kw| kw.0 == word)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_line_number(state: &mut State, result: &mut String, con: &HighlightConfig)
|
||||||
|
{
|
||||||
|
if !state.flag_nr {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if state.line_nr < 10 {
|
||||||
|
result.push_str(&format!("{}{} {}", con.color_numbers, state.line_nr, con.color_reset));
|
||||||
|
} else if state.line_nr < 100 {
|
||||||
|
result.push_str(&format!("{}{} {}", con.color_numbers, state.line_nr, con.color_reset));
|
||||||
|
} else {
|
||||||
|
result.push_str(&format!("{}{} {}", con.color_numbers, state.line_nr, con.color_reset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn highlight_line(line: &str, lang: Language, config: &HighlightConfig, result: &mut String, state: &mut State) -> bool
|
||||||
|
{
|
||||||
|
if state.stop_at_line <= state.line_nr {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
state.line_nr += 1;
|
||||||
|
append_line_number(state, result, config);
|
||||||
|
let mut p = line.chars().peekable();
|
||||||
|
while let Some(mut ch) = p.next() {
|
||||||
|
match lang {
|
||||||
|
Language::AsmX86 | Language::Asm8051 => {
|
||||||
|
if ch == ';' {
|
||||||
|
result.push_str(config.color_comment);
|
||||||
|
result.push(';');
|
||||||
|
for c in p { result.push(c); }
|
||||||
|
result.push_str(config.color_reset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Language::Python | Language::Shell => {
|
||||||
|
if ch == '#' {
|
||||||
|
result.push_str(config.color_comment);
|
||||||
|
result.push('#');
|
||||||
|
for c in p { result.push(c); }
|
||||||
|
result.push_str(config.color_reset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Language::JavaScript | Language::Docker => {
|
||||||
|
if ch == '/' && p.peek() == Some(&'/') {
|
||||||
|
result.push_str(config.color_comment);
|
||||||
|
result.push_str("//");
|
||||||
|
p.next();
|
||||||
|
for c in p {
|
||||||
|
result.push(c);
|
||||||
|
}
|
||||||
|
result.push_str(config.color_reset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Language::Clang => {
|
||||||
|
if ch == '/' {
|
||||||
|
match p.peek() {
|
||||||
|
Some(&'/') => {
|
||||||
|
result.push_str(config.color_comment);
|
||||||
|
result.push_str("//");
|
||||||
|
p.next();
|
||||||
|
for c in p {
|
||||||
|
result.push(c);
|
||||||
|
}
|
||||||
|
result.push_str(config.color_reset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Some(&'*') => {
|
||||||
|
result.push_str(config.color_comment);
|
||||||
|
result.push_str("/*");
|
||||||
|
p.next();
|
||||||
|
while let Some(c) = p.next() {
|
||||||
|
if c == '*' && p.peek() == Some(&'/') {
|
||||||
|
result.push('*');
|
||||||
|
result.push('/');
|
||||||
|
p.next();
|
||||||
|
result.push_str(config.color_reset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result.push(c);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Language::Sql => {
|
||||||
|
if ch == '/' && p.peek() == Some(&'*') {
|
||||||
|
result.push_str(config.color_comment);
|
||||||
|
result.push_str("/*");
|
||||||
|
p.next();
|
||||||
|
while let Some(c) = p.next() {
|
||||||
|
if c == '*' && p.peek() == Some(&'/') {
|
||||||
|
result.push('*');
|
||||||
|
result.push('/');
|
||||||
|
p.next();
|
||||||
|
result.push_str(config.color_reset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result.push(c);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
if ch == '"' || ch == '\'' {
|
||||||
|
let quote = ch;
|
||||||
|
result.push_str(config.color_string);
|
||||||
|
result.push(quote);
|
||||||
|
ch = match p.next() {
|
||||||
|
Some(c) => c,
|
||||||
|
None => { result.push_str(config.color_reset); break; }
|
||||||
|
};
|
||||||
|
while ch != quote {
|
||||||
|
if ch == '\\' {
|
||||||
|
result.push('\\');
|
||||||
|
if let Some(next) = p.next() {
|
||||||
|
result.push(next);
|
||||||
|
ch = match p.next() { Some(c) => c, None => break };
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.push(ch);
|
||||||
|
}
|
||||||
|
ch = match p.next() { Some(c) => c, None => break };
|
||||||
|
}
|
||||||
|
if ch == quote {
|
||||||
|
result.push(quote);
|
||||||
|
}
|
||||||
|
result.push_str(config.color_reset);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if lang == Language::Html && ch == '<' {
|
||||||
|
result.push_str(config.color_tag);
|
||||||
|
result.push('<');
|
||||||
|
ch = match p.next() { Some(c) => c, None => { result.push_str(config.color_reset); break; } };
|
||||||
|
while ch != '>' {
|
||||||
|
if ch == '"' {
|
||||||
|
let quote = ch;
|
||||||
|
result.push_str(config.color_string);
|
||||||
|
result.push(quote);
|
||||||
|
ch = match p.next() { Some(c) => c, None => break };
|
||||||
|
while ch != quote {
|
||||||
|
if ch == '\\' {
|
||||||
|
result.push('\\');
|
||||||
|
if let Some(n) = p.next() { result.push(n); ch = match p.next() { Some(c)=>c, None=>break }; continue; }
|
||||||
|
} else {
|
||||||
|
result.push(ch);
|
||||||
|
}
|
||||||
|
ch = match p.next() { Some(c) => c, None => break };
|
||||||
|
}
|
||||||
|
if ch == quote {
|
||||||
|
result.push(quote);
|
||||||
|
}
|
||||||
|
result.push_str(config.color_tag);
|
||||||
|
} else {
|
||||||
|
result.push(ch);
|
||||||
|
}
|
||||||
|
ch = match p.next() { Some(c) => c, None => break };
|
||||||
|
}
|
||||||
|
if ch == '>' {
|
||||||
|
result.push('>');
|
||||||
|
}
|
||||||
|
result.push_str(config.color_reset);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if is_word_char(ch) {
|
||||||
|
let mut buf = String::new();
|
||||||
|
buf.push(ch);
|
||||||
|
while let Some(&next) = p.peek() {
|
||||||
|
if is_word_char(next) && buf.len() < 250 {
|
||||||
|
buf.push(next);
|
||||||
|
p.next();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let is_kw = match lang {
|
||||||
|
Language::Python => is_keyword(&buf, PYTHON_KEYWORDS),
|
||||||
|
Language::JavaScript => is_keyword(&buf, JS_KEYWORDS),
|
||||||
|
Language::Clang => is_keyword(&buf, KEYWORDS_C),
|
||||||
|
Language::Shell => is_keyword(&buf, SHELL_KEYWORDS),
|
||||||
|
Language::Docker => is_keyword(&buf, DOCKER_KEYWORDS),
|
||||||
|
Language::AsmX86 => is_keyword(&buf, ASM_X86_KEYWORDS),
|
||||||
|
Language::Asm8051 => is_keyword(&buf, ASM_8051_KEYWORDS),
|
||||||
|
Language::Sql => is_keyword(&buf, SQL_KEYWORDS),
|
||||||
|
Language::Rust => is_keyword(&buf, RUST_KEYWORDS),
|
||||||
|
Language::LangDockerCompose => is_keyword(&buf, DOCKER_COMPOSE_KEYWORDS),
|
||||||
|
Language::LangJava => is_keyword(&buf, JAVA_KEYWORDS),
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
if is_kw {
|
||||||
|
result.push_str(config.color_keyword);
|
||||||
|
result.push_str(&buf);
|
||||||
|
result.push_str(config.color_reset);
|
||||||
|
} else {
|
||||||
|
result.push_str(&buf);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.push(ch);
|
||||||
|
}
|
||||||
|
result.push_str(config.new_line);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_binary_file(filepath: &str, output: &mut String, state: &mut State, config: &HighlightConfig) {
|
||||||
|
let bytes = match fs::read(filepath) {
|
||||||
|
Ok(b) => b,
|
||||||
|
Err(e) => {
|
||||||
|
output.push_str(&format!("Fehler beim Lesen der Datei: {}\n", e));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if bytes.is_empty() {
|
||||||
|
output.push_str("Datei ist leer.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut line_nr: u64 = 0;
|
||||||
|
for (i, chunk) in bytes.chunks(8).enumerate() {
|
||||||
|
output.push_str(config.color_header);
|
||||||
|
output.push_str(&format!("{:08x} ", i * 8));
|
||||||
|
output.push_str(config.color_reset);
|
||||||
|
if state.flag_nr == true {
|
||||||
|
output.push_str(config.color_string);
|
||||||
|
output.push_str(&format!("{:08} ", line_nr));
|
||||||
|
output.push_str(config.color_reset);
|
||||||
|
}
|
||||||
|
output.push_str(config.color_keyword);
|
||||||
|
let new_line_char: &u8 = &0xA;
|
||||||
|
for byte in chunk {
|
||||||
|
if byte == new_line_char {
|
||||||
|
line_nr += 1;
|
||||||
|
}
|
||||||
|
output.push_str(&format!("{:02x} ", byte));
|
||||||
|
}
|
||||||
|
output.push_str(config.color_reset);
|
||||||
|
output.push_str(config.color_comment);
|
||||||
|
for _ in chunk.len()..8 {
|
||||||
|
output.push_str(" ");
|
||||||
|
}
|
||||||
|
output.push_str(config.color_reset);
|
||||||
|
output.push_str(" |");
|
||||||
|
for &byte in chunk {
|
||||||
|
if (32..=126).contains(&byte) {
|
||||||
|
output.push(byte as char);
|
||||||
|
} else {
|
||||||
|
output.push('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output.push_str("|\n");
|
||||||
|
}
|
||||||
|
output.push_str(&format!("\n{} Bytes insgesamt.\n", bytes.len()));
|
||||||
|
}
|
||||||
|
|
||||||
Executable
+141
@@ -0,0 +1,141 @@
|
|||||||
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
pub struct Keyword(pub &'static str);
|
||||||
|
|
||||||
|
pub static DOCKER_COMPOSE_KEYWORDS: &[Keyword] = &[
|
||||||
|
Keyword("version"), Keyword("name"), Keyword("services"),
|
||||||
|
Keyword("volumes"), Keyword("configs"), Keyword("networks"),
|
||||||
|
Keyword("secrets"), Keyword("include"), Keyword("image"), Keyword("build"),
|
||||||
|
Keyword("context"), Keyword("dockerfile"), Keyword("args"),
|
||||||
|
Keyword("command"), Keyword("entrypoint"), Keyword("ports"), Keyword("expose"),
|
||||||
|
Keyword("environment"), Keyword("env_file"), Keyword("depends_on"),
|
||||||
|
Keyword("restart"), Keyword("deploy"), Keyword("labels"), Keyword("healthcheck"),
|
||||||
|
Keyword("working_dir"), Keyword("user"), Keyword("privileged"), Keyword("cap_add"),
|
||||||
|
Keyword("cap_drop"), Keyword("devices"), Keyword("dns"), Keyword("dns_search"),
|
||||||
|
Keyword("tmpfs"), Keyword("ulimits"), Keyword("stdin_open"), Keyword("tty"),
|
||||||
|
Keyword("profiles"), Keyword("scale"), Keyword("init"), Keyword("pid"), Keyword("ipc"),
|
||||||
|
Keyword("isolation"), Keyword("cpu_count"), Keyword("cpu_percent"), Keyword("cpu_shares"),
|
||||||
|
Keyword("cpu_quota"), Keyword("cpus"), Keyword("mem_limit"), Keyword("mem_reservation"),
|
||||||
|
Keyword("memswap_limit"), Keyword("shm_size"), Keyword("oom_score_adj"), Keyword("target"),
|
||||||
|
Keyword("cache_from"), Keyword("cache_to"), Keyword("extra_hosts"), Keyword("logging"),
|
||||||
|
Keyword("security_opt"), Keyword("stop_grace_period"), Keyword("stop_signal"),
|
||||||
|
Keyword("sysctls"), Keyword("platform"), Keyword("driver"), Keyword("driver_opts"),
|
||||||
|
Keyword("external"), Keyword("ipam"), Keyword("attachable"), Keyword("internal"),
|
||||||
|
Keyword("ipv6"), Keyword("file"), Keyword("content"),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub static RUST_KEYWORDS: &[Keyword] = &[
|
||||||
|
Keyword("fn"), Keyword("let"), Keyword("mut"), Keyword("match"), Keyword("if"),
|
||||||
|
Keyword("else"), Keyword("loop"), Keyword("while"), Keyword("for"), Keyword("in"),
|
||||||
|
Keyword("impl"), Keyword("struct"), Keyword("enum"), Keyword("trait"), Keyword("pub"),
|
||||||
|
Keyword("use"), Keyword("mod"), Keyword("where"), Keyword("type"), Keyword("move"),
|
||||||
|
Keyword("async"), Keyword("await"), Keyword("return"), Keyword("break"),
|
||||||
|
Keyword("continue"), Keyword("const"), Keyword("static"), Keyword("unsafe"),
|
||||||
|
Keyword("dyn"), Keyword("as"), Keyword("ref"), Keyword("true"), Keyword("false"),
|
||||||
|
Keyword("self"), Keyword("Self"), Keyword("crate"), Keyword("super"),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub static SQL_KEYWORDS: &[Keyword] = &[
|
||||||
|
Keyword("SELECT"), Keyword("FROM"), Keyword("WHERE"), Keyword("INSERT"),
|
||||||
|
Keyword("INTO"), Keyword("VALUES"), Keyword("UPDATE"), Keyword("SET"),
|
||||||
|
Keyword("DELETE"), Keyword("CREATE"), Keyword("TABLE"), Keyword("DROP"),
|
||||||
|
Keyword("ALTER"), Keyword("ADD"), Keyword("JOIN"), Keyword("INNER"),
|
||||||
|
Keyword("LEFT"), Keyword("RIGHT"), Keyword("FULL"), Keyword("ON"),
|
||||||
|
Keyword("GROUP"), Keyword("BY"), Keyword("ORDER"), Keyword("ASC"),
|
||||||
|
Keyword("DESC"), Keyword("DISTINCT"), Keyword("LIMIT"), Keyword("OFFSET"),
|
||||||
|
Keyword("UNION"), Keyword("ALL"), Keyword("AND"), Keyword("OR"),
|
||||||
|
Keyword("NOT"), Keyword("NULL"), Keyword("IS"), Keyword("IN"),
|
||||||
|
Keyword("LIKE"), Keyword("BETWEEN"), Keyword("EXISTS"), Keyword("CASE"),
|
||||||
|
Keyword("WHEN"), Keyword("THEN"), Keyword("ELSE"), Keyword("END"),
|
||||||
|
Keyword("PRIMARY"), Keyword("KEY"), Keyword("FOREIGN"), Keyword("REFERENCES"),
|
||||||
|
Keyword("INDEX"), Keyword("VIEW"), Keyword("AS"), Keyword("HAVING"),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub static ASM_X86_KEYWORDS: &[Keyword] = &[
|
||||||
|
Keyword("mov"), Keyword("add"), Keyword("adc"), Keyword("sub"), Keyword("sbb"),
|
||||||
|
Keyword("inc"), Keyword("dec"), Keyword("mul"), Keyword("imul"), Keyword("div"),
|
||||||
|
Keyword("idiv"), Keyword("and"), Keyword("or"), Keyword("xor"), Keyword("not"),
|
||||||
|
Keyword("neg"), Keyword("shl"), Keyword("shr"), Keyword("sal"), Keyword("sar"),
|
||||||
|
Keyword("rol"), Keyword("ror"), Keyword("rcl"), Keyword("rcr"), Keyword("cmp"),
|
||||||
|
Keyword("test"), Keyword("push"), Keyword("pop"), Keyword("pushf"), Keyword("popf"),
|
||||||
|
Keyword("pusha"), Keyword("popa"), Keyword("lea"), Keyword("xchg"),
|
||||||
|
Keyword("movsx"), Keyword("movzx"), Keyword("bswap"), Keyword("jmp"), Keyword("je"),
|
||||||
|
Keyword("jne"), Keyword("jg"), Keyword("jl"), Keyword("jge"), Keyword("jle"),
|
||||||
|
Keyword("ja"), Keyword("jb"), Keyword("jae"), Keyword("jbe"), Keyword("call"),
|
||||||
|
Keyword("ret"), Keyword("int"), Keyword("iret"), Keyword("loop"), Keyword("loope"),
|
||||||
|
Keyword("loopne"), Keyword("rep"), Keyword("repe"), Keyword("repne"),
|
||||||
|
Keyword("stos"), Keyword("lods"), Keyword("movs"), Keyword("cmps"), Keyword("scas"),
|
||||||
|
Keyword("cli"), Keyword("sti"), Keyword("hlt"), Keyword("nop"),
|
||||||
|
Keyword("syscall"), Keyword("sysret"), Keyword("movaps"), Keyword("addps"),
|
||||||
|
Keyword("mulps"), Keyword("movsd"), Keyword("addsd"), Keyword("mulsd"),
|
||||||
|
Keyword("vmovdqa64"), Keyword("vpcmpneqq"), Keyword("kmovd"), Keyword("vzeroupper"),
|
||||||
|
Keyword("vmovdqu"), Keyword("vmovdqa"), Keyword("vmovmskpd"), Keyword("vpmovmskb"),
|
||||||
|
Keyword("vmovdqu8"), Keyword("vpcmpneqb"), Keyword("kmovq"), Keyword("vpcmpeqq"),
|
||||||
|
Keyword("vpcmpeqb"), Keyword("jz")
|
||||||
|
];
|
||||||
|
|
||||||
|
pub static ASM_8051_KEYWORDS: &[Keyword] = &[
|
||||||
|
Keyword("NOP"), Keyword("AJMP"), Keyword("LJMP"), Keyword("SJMP"), Keyword("JMP"),
|
||||||
|
Keyword("ACALL"), Keyword("LCALL"), Keyword("RET"), Keyword("RETI"), Keyword("RR"),
|
||||||
|
Keyword("RL"), Keyword("RRC"), Keyword("RLC"), Keyword("INC"), Keyword("DEC"),
|
||||||
|
Keyword("ADD"), Keyword("ADDC"), Keyword("SUBB"), Keyword("DA"), Keyword("ANL"),
|
||||||
|
Keyword("ORL"), Keyword("XRL"), Keyword("CLR"), Keyword("CPL"), Keyword("MOV"),
|
||||||
|
Keyword("MOVC"), Keyword("MOVX"), Keyword("XCH"), Keyword("PUSH"), Keyword("POP"),
|
||||||
|
Keyword("SWAP"), Keyword("MUL"), Keyword("DIV"), Keyword("JB"), Keyword("JNB"),
|
||||||
|
Keyword("JC"), Keyword("JNC"), Keyword("JZ"), Keyword("JNZ"), Keyword("JBC"),
|
||||||
|
Keyword("DJNZ"), Keyword("CJNE"),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub static PYTHON_KEYWORDS: &[Keyword] = &[
|
||||||
|
Keyword("def"), Keyword("class"), Keyword("import"), Keyword("from"), Keyword("for"),
|
||||||
|
Keyword("while"), Keyword("if"), Keyword("elif"), Keyword("else"), Keyword("return"),
|
||||||
|
Keyword("True"), Keyword("False"), Keyword("None"), Keyword("with"), Keyword("as"),
|
||||||
|
Keyword("try"), Keyword("except"), Keyword("finally"), Keyword("in"), Keyword("is"),
|
||||||
|
Keyword("not"),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub static JS_KEYWORDS: &[Keyword] = &[
|
||||||
|
Keyword("function"), Keyword("const"), Keyword("let"), Keyword("var"), Keyword("if"),
|
||||||
|
Keyword("else"), Keyword("for"), Keyword("while"), Keyword("return"), Keyword("class"),
|
||||||
|
Keyword("import"), Keyword("from"), Keyword("export"), Keyword("true"), Keyword("false"),
|
||||||
|
Keyword("null"), Keyword("undefined"), Keyword("new"), Keyword("this"),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub static KEYWORDS_C: &[Keyword] = &[
|
||||||
|
Keyword("int"), Keyword("char"), Keyword("float"), Keyword("double"), Keyword("void"),
|
||||||
|
Keyword("return"), Keyword("if"), Keyword("else"), Keyword("for"), Keyword("while"),
|
||||||
|
Keyword("struct"), Keyword("typedef"), Keyword("enum"), Keyword("const"),
|
||||||
|
Keyword("static"), Keyword("unsigned"), Keyword("signed"), Keyword("long"),
|
||||||
|
Keyword("short"), Keyword("include"), Keyword("define"), Keyword("ifdef"), Keyword("endif"),
|
||||||
|
Keyword("pragma"), Keyword("error"), Keyword("do"), Keyword("ifndef"),
|
||||||
|
Keyword("size_t"), Keyword("ssize_t"), Keyword("undef"),
|
||||||
|
Keyword("defined"), Keyword("ifndef"), Keyword("elif"), Keyword("goto")
|
||||||
|
];
|
||||||
|
|
||||||
|
pub static SHELL_KEYWORDS: &[Keyword] = &[
|
||||||
|
Keyword("if"), Keyword("then"), Keyword("else"), Keyword("fi"), Keyword("for"),
|
||||||
|
Keyword("in"), Keyword("do"), Keyword("done"), Keyword("case"), Keyword("esac"),
|
||||||
|
Keyword("while"), Keyword("function"), Keyword("elif"),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub static DOCKER_KEYWORDS: &[Keyword] = &[
|
||||||
|
Keyword("FROM"), Keyword("RUN"), Keyword("CMD"), Keyword("ENTRYPOINT"), Keyword("COPY"),
|
||||||
|
Keyword("ADD"), Keyword("ENV"), Keyword("ARG"), Keyword("WORKDIR"), Keyword("EXPOSE"),
|
||||||
|
Keyword("USER"), Keyword("VOLUME"), Keyword("LABEL"), Keyword("ONBUILD"),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub static JAVA_KEYWORDS: &[Keyword] = &[
|
||||||
|
Keyword("abstract"), Keyword("assert"), Keyword("boolean"), Keyword("break"), Keyword("byte"),
|
||||||
|
Keyword("case"), Keyword("catch"), Keyword("char"), Keyword("class"), Keyword("const"),
|
||||||
|
Keyword("continue"), Keyword("default"), Keyword("do"), Keyword("double"), Keyword("else"),
|
||||||
|
Keyword("enum"), Keyword("extends"), Keyword("final"), Keyword("finally"), Keyword("float"),
|
||||||
|
Keyword("for"), Keyword("goto"), Keyword("if"), Keyword("implements"), Keyword("import"),
|
||||||
|
Keyword("instanceof"), Keyword("int"), Keyword("interface"), Keyword("long"), Keyword("native"),
|
||||||
|
Keyword("new"), Keyword("package"), Keyword("private"), Keyword("protected"), Keyword("public"),
|
||||||
|
Keyword("return"), Keyword("short"), Keyword("static"), Keyword("strictfp"), Keyword("super"),
|
||||||
|
Keyword("switch"), Keyword("synchronized"), Keyword("this"), Keyword("throw"), Keyword("throws"),
|
||||||
|
Keyword("transient"), Keyword("try"), Keyword("void"), Keyword("volatile"), Keyword("while"),
|
||||||
|
Keyword("true"), Keyword("false"), Keyword("null"),
|
||||||
|
Keyword("var"), Keyword("yield"), Keyword("record"), Keyword("sealed"), Keyword("permits"),
|
||||||
|
Keyword("non-sealed"), Keyword("when"),
|
||||||
|
];
|
||||||
|
|
||||||
Regular → Executable
Regular → Executable
Executable
+212
@@ -0,0 +1,212 @@
|
|||||||
|
use crate::state::State;
|
||||||
|
use crate::col::HighlightConfig;
|
||||||
|
|
||||||
|
const BINARY_LINE_LENGTH: usize = 48;
|
||||||
|
const HEADER_LENGTH_BYTE: u32 = 38;
|
||||||
|
|
||||||
|
pub fn print_hex_file(filepath: &str, state: &mut State, config: &HighlightConfig) {
|
||||||
|
let mut file: std::fs::File = match std::fs::File::open(filepath) {
|
||||||
|
Ok(opened_file) => opened_file,
|
||||||
|
Err(_) => {
|
||||||
|
println!("Fehler beim Lesen der Datei: {}", filepath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let file_size: u64 = match file.metadata() {
|
||||||
|
Ok(metadata) => metadata.len(),
|
||||||
|
Err(_) => {
|
||||||
|
println!("Fehler beim Lesen der Datei: {}", filepath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if file_size == 0 {
|
||||||
|
println!("Datei ist leer.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let file_size_usize: usize = file_size as usize;
|
||||||
|
let mut bytes: Vec<u8> = Vec::with_capacity(file_size_usize);
|
||||||
|
bytes.resize(file_size_usize, 0u8);
|
||||||
|
match std::io::Read::read_exact(&mut file, &mut bytes) {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(_) => {
|
||||||
|
println!("Fehler beim Lesen der Datei: {}", filepath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let bytes_read: usize = bytes.len();
|
||||||
|
let mut chunk_offset: usize = 0;
|
||||||
|
while chunk_offset < bytes_read {
|
||||||
|
let mut current_chunk_len: usize = bytes_read - chunk_offset;
|
||||||
|
if current_chunk_len > BINARY_LINE_LENGTH {
|
||||||
|
current_chunk_len = BINARY_LINE_LENGTH;
|
||||||
|
}
|
||||||
|
print!(
|
||||||
|
"{}{:08x} {}",
|
||||||
|
config.color_header,
|
||||||
|
chunk_offset,
|
||||||
|
config.color_reset
|
||||||
|
);
|
||||||
|
if state.flag_nr {
|
||||||
|
print!("{}{:08} {}", config.color_string, state.line_nr, config.color_reset);
|
||||||
|
}
|
||||||
|
print!("{}", config.color_keyword);
|
||||||
|
let mut byte_index: usize = 0;
|
||||||
|
while byte_index < current_chunk_len {
|
||||||
|
let current_byte: u8 = bytes[chunk_offset + byte_index];
|
||||||
|
if current_byte == b'\n' {
|
||||||
|
state.line_nr += 1;
|
||||||
|
}
|
||||||
|
print!("{:02x} ", current_byte);
|
||||||
|
byte_index += 1;
|
||||||
|
}
|
||||||
|
print!("{}", config.color_reset);
|
||||||
|
if current_chunk_len < 8 {
|
||||||
|
print!("{}", config.color_comment);
|
||||||
|
let mut pad_index: usize = current_chunk_len;
|
||||||
|
while pad_index < BINARY_LINE_LENGTH {
|
||||||
|
print!(" ");
|
||||||
|
pad_index += 1;
|
||||||
|
}
|
||||||
|
print!("{}", config.color_reset);
|
||||||
|
}
|
||||||
|
print!(" |");
|
||||||
|
byte_index = 0;
|
||||||
|
while byte_index < current_chunk_len {
|
||||||
|
let current_byte: u8 = bytes[chunk_offset + byte_index];
|
||||||
|
if current_byte >= 32 && current_byte <= 126 {
|
||||||
|
print!("{}", current_byte as char);
|
||||||
|
} else {
|
||||||
|
print!(".");
|
||||||
|
}
|
||||||
|
byte_index += 1;
|
||||||
|
}
|
||||||
|
println!("|");
|
||||||
|
chunk_offset += current_chunk_len;
|
||||||
|
}
|
||||||
|
println!("{}{}{}Bytes insgesamt.", config.new_line, bytes_read, config.new_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn log_highlight_line(line: &str, state: &mut State, config: &HighlightConfig) {
|
||||||
|
let line_bytes: &[u8] = line.as_bytes();
|
||||||
|
let mut index: usize = 0;
|
||||||
|
let mut stage: i32 = 0;
|
||||||
|
print_line_number(state, config);
|
||||||
|
state.line_nr += 1;
|
||||||
|
let mut char_counter: u32 = 0;
|
||||||
|
while index < line_bytes.len() {
|
||||||
|
let current_byte: u8 = line_bytes[index];
|
||||||
|
if current_byte == b'[' && char_counter < HEADER_LENGTH_BYTE {
|
||||||
|
if stage == 0 {
|
||||||
|
print!("{}[", config.color_timestamp);
|
||||||
|
index += 1;
|
||||||
|
while index < line_bytes.len() && line_bytes[index] != b']' {
|
||||||
|
print!("{}", line_bytes[index] as char);
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
if index < line_bytes.len() && line_bytes[index] == b']' {
|
||||||
|
print!("]{}", config.color_reset);
|
||||||
|
index += 1;
|
||||||
|
stage += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print!("{}[", config.color_ip);
|
||||||
|
index += 1;
|
||||||
|
while index < line_bytes.len() && line_bytes[index] != b']' {
|
||||||
|
print!("{}", line_bytes[index] as char);
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
if index < line_bytes.len() && line_bytes[index] == b']' {
|
||||||
|
print!("]{}", config.color_reset);
|
||||||
|
index += 1;
|
||||||
|
stage = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else if current_byte == b'0'
|
||||||
|
&& index + 3 < line_bytes.len()
|
||||||
|
&& line_bytes[index + 1] == b'x'
|
||||||
|
{
|
||||||
|
print!("{}0x", config.color_hex);
|
||||||
|
index += 2;
|
||||||
|
print!("{}", line_bytes[index] as char);
|
||||||
|
index += 1;
|
||||||
|
print!("{} ", line_bytes[index] as char);
|
||||||
|
index += 1;
|
||||||
|
print!("{}", config.color_reset);
|
||||||
|
if index < line_bytes.len() && line_bytes[index] == b' ' {
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
print!("{}", current_byte as char);
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
char_counter += 1;
|
||||||
|
}
|
||||||
|
print!("{}", config.new_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_c_array(filename: &str, config: &HighlightConfig) {
|
||||||
|
let mut input_file: std::fs::File = match std::fs::File::open(filename) {
|
||||||
|
Ok(opened_file) => opened_file,
|
||||||
|
Err(_) => {
|
||||||
|
eprintln!("Fehler: Datei {} konnte nicht geöffnet werden", filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let file_size_u64: u64 = match input_file.metadata() {
|
||||||
|
Ok(metadata) => metadata.len(),
|
||||||
|
Err(_) => {
|
||||||
|
eprintln!("Fehler: ftell fehlgeschlagen");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let file_size: usize = file_size_u64 as usize;
|
||||||
|
let mut data_buffer: Vec<u8> = Vec::with_capacity(file_size);
|
||||||
|
data_buffer.resize(file_size, 0u8);
|
||||||
|
if file_size > 0 {
|
||||||
|
match std::io::Read::read_exact(&mut input_file, &mut data_buffer) {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(_) => {
|
||||||
|
eprintln!("Fehler: Datei konnte nicht vollständig gelesen werden");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("{}const unsigned char BUFF[1822][4] = {{", config.color_keyword);
|
||||||
|
let mut index: usize = 0;
|
||||||
|
while index < file_size {
|
||||||
|
if index % 16 == 0 {
|
||||||
|
print!(" ");
|
||||||
|
}
|
||||||
|
print!("{}0x{:08X}{}", config.color_numbers, data_buffer[index], config.color_reset);
|
||||||
|
if index + 1 < file_size {
|
||||||
|
print!(", ");
|
||||||
|
}
|
||||||
|
if (index + 1) % 16 == 0 {
|
||||||
|
println!("");
|
||||||
|
}
|
||||||
|
if index > (16 * 1822) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
println!("");
|
||||||
|
println!("{}}};{}", config.color_keyword, config.color_reset);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_line_number(state: &State, config: &HighlightConfig) {
|
||||||
|
if !state.flag_nr {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let line_nr = state.line_nr;
|
||||||
|
let formatted_line = if line_nr < 10 {
|
||||||
|
format!("{}{} {}", config.color_header, line_nr, config.color_reset)
|
||||||
|
} else if line_nr < 100 {
|
||||||
|
format!("{}{} {}", config.color_header, line_nr, config.color_reset)
|
||||||
|
} else {
|
||||||
|
format!("{}{} {}", config.color_header, line_nr, config.color_reset)
|
||||||
|
};
|
||||||
|
print!("{}", formatted_line);
|
||||||
|
}
|
||||||
|
|
||||||
Regular → Executable
Reference in New Issue
Block a user