Add libclide. #23
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1174,6 +1174,7 @@ dependencies = [
|
||||
"libclide-macros",
|
||||
"log",
|
||||
"strum",
|
||||
"syntect",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -9,3 +9,4 @@ strum = { workspace = true }
|
||||
log = { workspace = true }
|
||||
devicons = { workspace = true }
|
||||
libclide-macros = { path = "../libclide-macros" }
|
||||
syntect = "5.3.0"
|
||||
|
||||
@@ -4,4 +4,21 @@
|
||||
|
||||
pub mod entry_meta;
|
||||
|
||||
use anyhow::Context;
|
||||
pub use entry_meta::icon;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn read_file<P: AsRef<Path>>(p: P) -> anyhow::Result<String> {
|
||||
let path = p.as_ref();
|
||||
let meta =
|
||||
fs::metadata(path).unwrap_or_else(|_| panic!("Failed to get file metadata {path:?}"));
|
||||
if !meta.is_file() {
|
||||
crate::warn!(target:"FileSystem", "Attempted to open file {path:?} that is not a valid file");
|
||||
Err(anyhow::anyhow!(
|
||||
"Attempted to open file {path:?} that is not a valid file"
|
||||
))?;
|
||||
}
|
||||
let path_str = path.to_string_lossy().to_string();
|
||||
fs::read_to_string(path_str.as_str()).context(format!("Failed to read file {path:?}"))
|
||||
}
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
// SPDX-License-Identifier: GNU General Public License v3.0 or later
|
||||
|
||||
pub mod colors;
|
||||
pub mod highlighter;
|
||||
|
||||
66
libclide/src/theme/highlighter.rs
Normal file
66
libclide/src/theme/highlighter.rs
Normal file
@@ -0,0 +1,66 @@
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use syntect::easy::HighlightLines;
|
||||
use syntect::highlighting::ThemeSet;
|
||||
use syntect::html::{IncludeBackground, append_highlighted_html_for_styled_line};
|
||||
use syntect::parsing::SyntaxSet;
|
||||
use syntect::util::LinesWithEndings;
|
||||
|
||||
pub struct Highlighter {
|
||||
path: String,
|
||||
ss: SyntaxSet,
|
||||
ts: ThemeSet,
|
||||
}
|
||||
|
||||
impl Highlighter {
|
||||
pub fn new<P: AsRef<Path>>(p: P) -> anyhow::Result<Highlighter> {
|
||||
let path = p.as_ref();
|
||||
let meta =
|
||||
fs::metadata(path).unwrap_or_else(|_| panic!("Failed to get file metadata {path:?}"));
|
||||
let ss = SyntaxSet::load_defaults_nonewlines();
|
||||
let ts = ThemeSet::load_defaults();
|
||||
if !meta.is_file() {
|
||||
crate::error!(target:"FileSystem", "Attempted to open file {path:?} that is not a valid file");
|
||||
Err(anyhow::anyhow!(
|
||||
"Attempted to open file {path:?} that is not a valid file"
|
||||
))?;
|
||||
}
|
||||
Ok(Highlighter {
|
||||
path: path.to_string_lossy().to_string(),
|
||||
ss,
|
||||
ts,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn syntax_highlight_text<P: AsRef<str>>(&self, p: P) -> String {
|
||||
let text = p.as_ref();
|
||||
let theme = &self.ts.themes["base16-ocean.dark"];
|
||||
let lang = self
|
||||
.ss
|
||||
.find_syntax_by_extension(
|
||||
Path::new(self.path.as_str())
|
||||
.extension()
|
||||
.map(|s| s.to_str())
|
||||
.unwrap_or_else(|| Some("md"))
|
||||
.expect("Failed to get file extension"),
|
||||
)
|
||||
.unwrap_or_else(|| self.ss.find_syntax_plain_text());
|
||||
let mut highlighter = HighlightLines::new(lang, theme);
|
||||
// If you care about the background, see `start_highlighted_html_snippet(theme);`.
|
||||
let mut output = String::from("<pre>\n");
|
||||
for line in LinesWithEndings::from(text) {
|
||||
let regions = highlighter
|
||||
.highlight_line(line, &self.ss)
|
||||
.expect("Failed to highlight");
|
||||
|
||||
append_highlighted_html_for_styled_line(
|
||||
®ions[..],
|
||||
IncludeBackground::No,
|
||||
&mut output,
|
||||
)
|
||||
.expect("Failed to insert highlighted html");
|
||||
}
|
||||
output.push_str("</pre>\n");
|
||||
output
|
||||
}
|
||||
}
|
||||
@@ -4,13 +4,9 @@
|
||||
|
||||
use cxx_qt_lib::{QModelIndex, QString};
|
||||
use dirs;
|
||||
use libclide::error;
|
||||
use libclide::theme::highlighter::Highlighter;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use syntect::easy::HighlightLines;
|
||||
use syntect::highlighting::ThemeSet;
|
||||
use syntect::html::{IncludeBackground, append_highlighted_html_for_styled_line};
|
||||
use syntect::parsing::SyntaxSet;
|
||||
use syntect::util::LinesWithEndings;
|
||||
|
||||
#[cxx_qt::bridge]
|
||||
pub mod qobject {
|
||||
@@ -70,49 +66,15 @@ impl Default for FileSystemImpl {
|
||||
|
||||
impl qobject::FileSystem {
|
||||
fn read_file(&self, path: &QString) -> QString {
|
||||
if path.is_empty() {
|
||||
return QString::default();
|
||||
}
|
||||
let meta = fs::metadata(path.to_string())
|
||||
.unwrap_or_else(|_| panic!("Failed to get file metadata {path:?}"));
|
||||
if !meta.is_file() {
|
||||
libclide::warn!(target:"FileSystem", "Attempted to open file {path:?} that is not a valid file");
|
||||
return QString::default();
|
||||
}
|
||||
let path_str = path.to_string();
|
||||
if let Ok(lines) = fs::read_to_string(path_str.as_str()) {
|
||||
let ss = SyntaxSet::load_defaults_nonewlines();
|
||||
let ts = ThemeSet::load_defaults();
|
||||
let theme = &ts.themes["base16-ocean.dark"];
|
||||
let lang = ss
|
||||
.find_syntax_by_extension(
|
||||
Path::new(path_str.as_str())
|
||||
.extension()
|
||||
.map(|s| s.to_str())
|
||||
.unwrap_or_else(|| Some("md"))
|
||||
.expect("Failed to get file extension"),
|
||||
)
|
||||
.unwrap_or_else(|| ss.find_syntax_plain_text());
|
||||
let mut highlighter = HighlightLines::new(lang, theme);
|
||||
// If you care about the background, see `start_highlighted_html_snippet(theme);`.
|
||||
let mut output = String::from("<pre>\n");
|
||||
for line in LinesWithEndings::from(lines.as_str()) {
|
||||
let regions = highlighter
|
||||
.highlight_line(line, &ss)
|
||||
.expect("Failed to highlight");
|
||||
|
||||
append_highlighted_html_for_styled_line(
|
||||
®ions[..],
|
||||
IncludeBackground::No,
|
||||
&mut output,
|
||||
)
|
||||
.expect("Failed to insert highlighted html");
|
||||
}
|
||||
|
||||
output.push_str("</pre>\n");
|
||||
QString::from(output)
|
||||
let text = libclide::fs::read_file(path.to_string()).unwrap_or_else(|_| {
|
||||
error!(target: "qobject::FileSystem", "Failed to read file at path {path:?}");
|
||||
String::default()
|
||||
});
|
||||
if let Ok(highlighter) = Highlighter::new(path.to_string()) {
|
||||
QString::from(highlighter.syntax_highlight_text(text))
|
||||
} else {
|
||||
QString::default()
|
||||
error!(target: "qobject::FileSystem", "Failed to create highlighter");
|
||||
QString::from(text)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user