mirror of
https://github.com/Xevion/find-syntax.git
synced 2025-12-05 23:14:57 -06:00
Initial implementation
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/target
|
||||
1278
Cargo.lock
generated
Normal file
1278
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
15
Cargo.toml
Normal file
15
Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "find-syntax"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.4.5", features = ["derive"] }
|
||||
env_logger = "0.10.0"
|
||||
log = "0.4.20"
|
||||
path-clean = "1.0.1"
|
||||
regex = "1.9.5"
|
||||
reqwest = { version = "0.11.20", features = ["blocking", "json"] }
|
||||
serde = { version = "1.0.188", features = ["derive"] }
|
||||
26
src/languages.rs
Normal file
26
src/languages.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
use regex::Regex;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::markdown::get_client;
|
||||
|
||||
const LANGUAGES_YML_URL: &str =
|
||||
"https://raw.githubusercontent.com/github-linguist/linguist/master/lib/linguist/languages.yml";
|
||||
|
||||
const EXTENSION_PATTERN: &str = r#"(?m)^\s*extensions:\s+-\s+"\.([\w\d]+)""#;
|
||||
|
||||
// Find all lines that look like `- ".ext"` and extract the extension. Each extension should be added to the set returned.
|
||||
pub fn get_languages() -> Result<HashSet<String>, Box<dyn std::error::Error>> {
|
||||
let client = get_client();
|
||||
let mut languages = HashSet::new();
|
||||
let languages_yml = client.get(LANGUAGES_YML_URL).send()?.text()?;
|
||||
let pattern = Regex::new(EXTENSION_PATTERN)?;
|
||||
|
||||
pattern
|
||||
.captures_iter(languages_yml.as_str())
|
||||
.for_each(|captures| {
|
||||
let extension = captures.get(1).unwrap().as_str();
|
||||
languages.insert(extension.to_string());
|
||||
});
|
||||
|
||||
Ok(languages)
|
||||
}
|
||||
76
src/main.rs
Normal file
76
src/main.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
use std::{path::{Path, PathBuf}, io, env, fs::create_dir_all};
|
||||
|
||||
use clap::Parser;
|
||||
use log::{debug, error, info, trace, warn};
|
||||
|
||||
use path_clean::PathClean;
|
||||
|
||||
mod languages;
|
||||
mod markdown;
|
||||
|
||||
pub fn absolute_path(path: impl AsRef<Path>) -> PathBuf {
|
||||
let path = path.as_ref();
|
||||
|
||||
let absolute_path = if path.is_absolute() {
|
||||
path.to_path_buf()
|
||||
} else {
|
||||
env::current_dir().expect("").join(path)
|
||||
}.clean();
|
||||
|
||||
absolute_path
|
||||
}
|
||||
|
||||
|
||||
/// Simple program to greet a person
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
#[arg()]
|
||||
file: String,
|
||||
|
||||
#[arg(short, long, default_value = "./.cache")]
|
||||
cache_dir: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
env_logger::init();
|
||||
|
||||
let cache_dir = absolute_path(Path::new(&args.cache_dir));
|
||||
debug!("Cache directory: {}", cache_dir.display());
|
||||
|
||||
if !cache_dir.exists() {
|
||||
debug!("Cache directory does not exist; creating...");
|
||||
create_dir_all(cache_dir).unwrap();
|
||||
}
|
||||
|
||||
// TODO: Given an input file argument, read the file.
|
||||
let file = absolute_path(Path::new(&args.file));
|
||||
debug!("File: {}", file.display());
|
||||
|
||||
if !file.exists() {
|
||||
error!("File does not exist: {}", file.display());
|
||||
return;
|
||||
}
|
||||
|
||||
// Function to generate a formatted markdown document of the file.
|
||||
let get_formatted_file = |language: &str, content: &str| -> String {
|
||||
format!("```{language}\n{content}\n```")
|
||||
};
|
||||
|
||||
|
||||
// Determine all available languages for highlighting abilities.
|
||||
let languages = languages::get_languages().unwrap();
|
||||
debug!("{} unique languages found.", languages.len());
|
||||
|
||||
// TODO: Begin querying GitHub Markdown API
|
||||
languages.iter().for_each(|language| {
|
||||
let markdown = markdown::get_markdown(&get_formatted_file(language, "Hello, world!")).unwrap();
|
||||
debug!("Markdown: {}", markdown);
|
||||
});
|
||||
|
||||
|
||||
// TODO: Cache responses locally
|
||||
// TODO: Determine complexity & level of colorization for each response
|
||||
// TODO: Provide a report of what syntax highlighting works best
|
||||
}
|
||||
37
src/markdown.rs
Normal file
37
src/markdown.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
use reqwest::blocking::Client;
|
||||
|
||||
const MARKDOWN_API_ENDPOINT: &str = "https://api.github.com/markdown";
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct MarkdownRequest {
|
||||
text: String,
|
||||
#[serde(skip_serializing_if = "String::is_empty")]
|
||||
mode: String,
|
||||
#[serde(skip_serializing_if = "String::is_empty")]
|
||||
context: String,
|
||||
}
|
||||
|
||||
pub fn get_client() -> Client {
|
||||
let client = Client::builder()
|
||||
.user_agent("xevion-find-syntax")
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
client
|
||||
}
|
||||
|
||||
pub fn get_markdown(text: &str) -> Result<String, Box<dyn std::error::Error>> {
|
||||
let client = get_client();
|
||||
|
||||
let request = MarkdownRequest {
|
||||
text: text.to_string(),
|
||||
mode: "".to_string(),
|
||||
context: "".to_string()
|
||||
};
|
||||
|
||||
let response = client.post(MARKDOWN_API_ENDPOINT).json(&request).send()?;
|
||||
let markdown = response.text()?;
|
||||
|
||||
Ok(markdown)
|
||||
}
|
||||
Reference in New Issue
Block a user