Board logo

标题: [文本处理] bbhlt - 可能是你见过的最强大的论坛代码高亮工具 [打印本页]

作者: bailong360    时间: 2019-10-30 23:48     标题: bbhlt - 可能是你见过的最强大的论坛代码高亮工具

本帖最后由 bailong360 于 2019-10-31 00:18 编辑

闲来无事写了一个论坛代码高亮工具, 顺便宣传一波 Rust

超好用的包管理 + 强大的宏 + 强大的静态类型系统 + 与 C/C++ 同一级别的运行速度 + 无 GC 下的内存安全 + 函数式 + 究极友好的文档系统 + ...
什么叫现代语言啊? (仰头
这就叫现代语言 (逃

use failure::{format_err, Error};
use std::fmt::Write;
use std::fs::read_to_string;
use std::path::PathBuf;
use structopt::StructOpt;
use syntect::dumps;
use syntect::easy::HighlightLines;
use syntect::highlighting::{Color, Style, ThemeSet};
use syntect::parsing::SyntaxSet;
use syntect::util::LinesWithEndings;

#[derive(StructOpt)]
#[structopt(name = "bbhlt")]
struct Config {
    /// 指定代码语言, 不指定则自动推断
    #[structopt(short, value_name = "LANG", long)]
    pub language: Option<String>,

    /// 代码高亮主题
    #[structopt(short, value_name = "THEME", long, default_value = "Dracula")]
    pub theme: String,

    /// 字体大小
    #[structopt(short, value_name = "SIZE", long, default_value = "12px")]
    pub size: String,

    /// 等待高亮的文件
    #[structopt(value_name = "FILE", parse(from_os_str))]
    pub path: PathBuf,
}

fn init_syntect() -> (SyntaxSet, ThemeSet) {
    (
        dumps::from_binary(include_bytes!("../assets/syntaxes.bin")),
        dumps::from_binary(include_bytes!("../assets/themes.bin")),
    )
}

fn rgb_to_hex(c: Color) -> String {
    format!("#{:02x}{:02x}{:02x}", c.r, c.g, c.b)
}

fn as_discuz_bbcode(v: &[(Style, &str)]) -> String {
    let mut s: String = String::new();
    for &(ref style, text) in v.iter() {
        write!(
            s,
            "【color={}]{}【/color]",
            rgb_to_hex(style.foreground),
            text,
        )
        .unwrap();
    }
    s
}

fn run(config: &Config) -> Result<(), Error> {
    let (ps, ts) = init_syntect();

    let syntax = if let Some(lang) = &config.language {
        ps.find_syntax_by_name(lang)
    } else {
        ps.find_syntax_for_file(config.path.to_str().unwrap())?
    };
    let syntax = syntax.ok_or_else(|| format_err!("无法确定语言"))?;
    let theme = ts.themes.get(&config.theme).ok_or_else(|| format_err!("未找到该主题"))?;

    let mut h = HighlightLines::new(syntax, theme);
    let mut bg = Color::WHITE;

    let code = read_to_string(&config.path)?;
    let body = LinesWithEndings::from(&code)
        .map(|line| {
            let ranges = h.highlight(line, &ps);
            bg = ranges[0].0.background;
            as_discuz_bbcode(&ranges)
        })
        .collect::<Vec<_>>()
        .join("");

    print!(
        "【table=100%,{}]【tr]【td]【font=monospace]【size={}]",
        rgb_to_hex(bg),
        config.size
    );
    print!("{}", body);
    println!("【/size]【/font]【/td]【/tr]【/table]");

    Ok(())
}

fn main() {
    let config: Config = Config::from_args();
    match run(&config) {
        Err(e) => eprintln!("ERROR:\n{}", e),
        _ => (),
    }
}


(因为 bbcode 不支持转义,所以我将代码中的部分中括号替换成了全角字符,避免看起来一团糟


链接: https://pan.baidu.com/s/1RqvEkD0Ogz7zRrxgh6NbSg 提取码: bxxj
作者: bailong360    时间: 2019-10-31 00:06

本帖最后由 bailong360 于 2019-10-31 00:15 编辑

可用的主题


1337
:: 这么浪费空间, Batcher 会不会打我 (
@echo off
setlocal enabledelayedexpansion
set n=0
for /l %%i in (1 1 100) do (
    set /a n+=1
    echo !n!
)
echo %n%
pause&exit


DarkNeon
:: 这么浪费空间, Batcher 会不会打我 (
@echo off
setlocal enabledelayedexpansion
set n=0
for /l %%i in (1 1 100) do (
    set /a n+=1
    echo !n!
)
echo %n%
pause&exit


Dracula
:: 这么浪费空间, Batcher 会不会打我 (
@echo off
setlocal enabledelayedexpansion
set n=0
for /l %%i in (1 1 100) do (
    set /a n+=1
    echo !n!
)
echo %n%
pause&exit


GitHub
:: 这么浪费空间, Batcher 会不会打我 (
@echo off
setlocal enabledelayedexpansion
set n=0
for /l %%i in (1 1 100) do (
    set /a n+=1
    echo !n!
)
echo %n%
pause&exit


Monokai Extended
:: 这么浪费空间, Batcher 会不会打我 (
@echo off
setlocal enabledelayedexpansion
set n=0
for /l %%i in (1 1 100) do (
    set /a n+=1
    echo !n!
)
echo %n%
pause&exit


Monokai Extended Bright
:: 这么浪费空间, Batcher 会不会打我 (
@echo off
setlocal enabledelayedexpansion
set n=0
for /l %%i in (1 1 100) do (
    set /a n+=1
    echo !n!
)
echo %n%
pause&exit


Monokai Extended Light
:: 这么浪费空间, Batcher 会不会打我 (
@echo off
setlocal enabledelayedexpansion
set n=0
for /l %%i in (1 1 100) do (
    set /a n+=1
    echo !n!
)
echo %n%
pause&exit


Monokai Extended Origin
:: 这么浪费空间, Batcher 会不会打我 (
@echo off
setlocal enabledelayedexpansion
set n=0
for /l %%i in (1 1 100) do (
    set /a n+=1
    echo !n!
)
echo %n%
pause&exit


OneHalfDark
:: 这么浪费空间, Batcher 会不会打我 (
@echo off
setlocal enabledelayedexpansion
set n=0
for /l %%i in (1 1 100) do (
    set /a n+=1
    echo !n!
)
echo %n%
pause&exit


OneHalfLight
:: 这么浪费空间, Batcher 会不会打我 (
@echo off
setlocal enabledelayedexpansion
set n=0
for /l %%i in (1 1 100) do (
    set /a n+=1
    echo !n!
)
echo %n%
pause&exit


Sublime Snazzy
:: 这么浪费空间, Batcher 会不会打我 (
@echo off
setlocal enabledelayedexpansion
set n=0
for /l %%i in (1 1 100) do (
    set /a n+=1
    echo !n!
)
echo %n%
pause&exit


TwoDark
:: 这么浪费空间, Batcher 会不会打我 (
@echo off
setlocal enabledelayedexpansion
set n=0
for /l %%i in (1 1 100) do (
    set /a n+=1
    echo !n!
)
echo %n%
pause&exit


zenburn
:: 这么浪费空间, Batcher 会不会打我 (
@echo off
setlocal enabledelayedexpansion
set n=0
for /l %%i in (1 1 100) do (
    set /a n+=1
    echo !n!
)
echo %n%
pause&exit

作者: bailong360    时间: 2019-10-31 00:20

理论上支持高亮混编代码应该也是可以的
但是我太懒了(

反正也可以手动拼接(逃(或者再做个工具来帮忙拼接
作者: codegay    时间: 2019-10-31 01:00


你代码里的“    s”
是不是多出来的。
作者: bailong360    时间: 2019-10-31 01:08

回复 4# codegay

不是, 这个其实相当于 return s;
由于 Rust 会将函数中最后一个表达式的值当成返回值
所以这个地方可以省略 return




欢迎光临 批处理之家 (http://bathome.net./) Powered by Discuz! 7.2