mirror of
https://git.vulpinecitrus.info/Lymkwi/estrus-navigator.git
synced 2024-12-04 15:56:36 +00:00
Implement display of identifiers
- Implement identifier types and display - Move all of it into its own submodule - Parse CLI args as the list of identifiers to fetch
This commit is contained in:
parent
1dac97b2dc
commit
6d2b3ead16
|
@ -11,3 +11,6 @@ license = "ACSL"
|
||||||
reqwest = { version = "0.11.22", features = ["default-tls", "json", "gzip"] }
|
reqwest = { version = "0.11.22", features = ["default-tls", "json", "gzip"] }
|
||||||
serde = { version = "1.0.190", features = ["derive"] }
|
serde = { version = "1.0.190", features = ["derive"] }
|
||||||
tokio = { version = "1.33.0", features = ["rt-multi-thread", "macros", "net"] }
|
tokio = { version = "1.33.0", features = ["rt-multi-thread", "macros", "net"] }
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "estrus"
|
||||||
|
|
4
README.md
Normal file
4
README.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Estrus Elixir Navigator
|
||||||
|
===
|
||||||
|
|
||||||
|
CLI navigator for the Elixir linux project.
|
182
src/ident.rs
Normal file
182
src/ident.rs
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
//! Structures structuring identifiers
|
||||||
|
//!
|
||||||
|
|
||||||
|
use std::fmt::{self, Display};
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
use std::marker::PhantomData as Phantom;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use serde::de::{self, Deserializer, Visitor};
|
||||||
|
|
||||||
|
use reqwest::Client;
|
||||||
|
|
||||||
|
/// Response to an query on the Elixir API
|
||||||
|
///
|
||||||
|
/// Holds the deserialized response to a query to the elixir API regarding definitions, references,
|
||||||
|
/// and documentation of an identifier.
|
||||||
|
#[derive(serde::Deserialize, Debug, Default)]
|
||||||
|
pub struct Response {
|
||||||
|
/// List of definitions
|
||||||
|
definitions: Vec<Definition>,
|
||||||
|
/// List of references
|
||||||
|
references: Vec<Reference>,
|
||||||
|
/// List of positions in the documentation
|
||||||
|
documentations: Vec<Documentation>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Response {
|
||||||
|
/// Retrieve definitions of the identifier
|
||||||
|
pub fn get_definitions(&self) -> &[Definition] {
|
||||||
|
&self.definitions
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve references of the identifier
|
||||||
|
pub fn get_references(&self) -> &[Reference] {
|
||||||
|
&self.references
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve documentation for the identifier
|
||||||
|
pub fn get_documentations(&self) -> &[Documentation] {
|
||||||
|
&self.documentations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, Debug)]
|
||||||
|
/// Different possible types of ifier Definitions
|
||||||
|
pub enum DefinitionType {
|
||||||
|
#[serde(rename(deserialize = "prototype"))]
|
||||||
|
Prototype,
|
||||||
|
#[serde(rename(deserialize = "member"))]
|
||||||
|
Member,
|
||||||
|
#[serde(rename(deserialize = "function"))]
|
||||||
|
Function,
|
||||||
|
#[serde(rename(deserialize = "enumerator"))]
|
||||||
|
Enumerator,
|
||||||
|
#[serde(rename(deserialize = "struct"))]
|
||||||
|
Struct,
|
||||||
|
#[serde(rename(deserialize = "variable"))]
|
||||||
|
Variable,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for DefinitionType {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Definition {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"[{:^9}] {}:{}",
|
||||||
|
self.deftype.to_string(),
|
||||||
|
self.path.to_str().unwrap_or("<???>"),
|
||||||
|
self.line
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, Debug)]
|
||||||
|
pub struct Definition {
|
||||||
|
path: PathBuf,
|
||||||
|
line: u32,
|
||||||
|
#[serde(rename(deserialize = "type"))]
|
||||||
|
deftype: DefinitionType,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn comma_separated<'de, V, T, D>(deserializer: D) -> Result<V, D::Error>
|
||||||
|
where
|
||||||
|
V: FromIterator<T>,
|
||||||
|
T: FromStr,
|
||||||
|
T::Err: Display,
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct CommaSeparated<V, T>(Phantom<V>, Phantom<T>);
|
||||||
|
|
||||||
|
impl<'de, V, T> Visitor<'de> for CommaSeparated<V, T>
|
||||||
|
where
|
||||||
|
V: FromIterator<T>,
|
||||||
|
T: FromStr,
|
||||||
|
T::Err: Display,
|
||||||
|
{
|
||||||
|
type Value = V;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("string containing comma-separated elements")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
s.split(',')
|
||||||
|
.map(FromStr::from_str)
|
||||||
|
.collect::<Result<Self::Value, _>>()
|
||||||
|
.map_err(de::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let visitor = CommaSeparated(Phantom, Phantom);
|
||||||
|
deserializer.deserialize_str(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, Debug)]
|
||||||
|
pub struct Reference {
|
||||||
|
path: PathBuf,
|
||||||
|
#[serde(deserialize_with = "comma_separated")]
|
||||||
|
line: Vec<u32>,
|
||||||
|
//#[serde(rename(serialize = "type"))]
|
||||||
|
//reftype: Option<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Reference {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}:{}",
|
||||||
|
self.path.to_str().unwrap_or("<???>"),
|
||||||
|
self.line
|
||||||
|
.iter()
|
||||||
|
.map(u32::to_string)
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(",")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, Debug)]
|
||||||
|
pub struct Documentation {
|
||||||
|
path: PathBuf,
|
||||||
|
#[serde(deserialize_with = "comma_separated")]
|
||||||
|
line: Vec<u32>,
|
||||||
|
//#[serde(rename(serialize = "type"))]
|
||||||
|
//doctype: Option<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Documentation {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}:{}",
|
||||||
|
self.path.to_str().unwrap_or("<???>"),
|
||||||
|
self.line
|
||||||
|
.iter()
|
||||||
|
.map(u32::to_string)
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(",")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn find(ident: &str) -> Response {
|
||||||
|
let client = Client::new();
|
||||||
|
let res = client
|
||||||
|
.get(format!(
|
||||||
|
"https://elixir.bootlin.com/api/ident/linux/{ident}?version=latest"
|
||||||
|
))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.expect("No future failure");
|
||||||
|
res.json::<Response>().await.expect("No failure")
|
||||||
|
}
|
82
src/main.rs
82
src/main.rs
|
@ -1,60 +1,40 @@
|
||||||
//! Main module for the project
|
//! Main module for the project
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use std::path::PathBuf;
|
#![deny(clippy::perf)]
|
||||||
|
#![deny(clippy::pedantic)]
|
||||||
|
#![deny(clippy::complexity)]
|
||||||
|
#![deny(clippy::correctness)]
|
||||||
|
|
||||||
use reqwest::Client;
|
use std::env::args;
|
||||||
|
|
||||||
/// Response to an Ident query on the Elixir API
|
mod ident;
|
||||||
///
|
|
||||||
/// Holds the deserialized response to a query to the elixir API regarding definitions, references,
|
|
||||||
/// and documentation of an identifier.
|
|
||||||
#[derive(serde::Deserialize, Debug)]
|
|
||||||
struct IdentResponse {
|
|
||||||
/// List of definitions
|
|
||||||
definitions: Vec<IdentDefinition>,
|
|
||||||
/// List of references
|
|
||||||
references: Vec<IdentReference>,
|
|
||||||
/// List of positions in the documentation
|
|
||||||
documentations: Vec<IdentDocumentation>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug)]
|
|
||||||
/// Different possible types of Identifier Definitions
|
|
||||||
enum IdentDefinitionType {
|
|
||||||
Prototype,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug)]
|
|
||||||
struct IdentDefinition {
|
|
||||||
path: PathBuf,
|
|
||||||
line: u32,
|
|
||||||
deftype: IdentDefinitionType,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug)]
|
|
||||||
struct IdentReference {
|
|
||||||
path: PathBuf,
|
|
||||||
line: u32,
|
|
||||||
reftype: Option<()>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug)]
|
|
||||||
struct IdentDocumentation {
|
|
||||||
path: PathBuf,
|
|
||||||
line: u32,
|
|
||||||
doctype: Option<()>
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn find_ident(ident: &str) -> IdentResponse {
|
|
||||||
let client = Client::new();
|
|
||||||
let res = client.get(format!("https://elixir.bootlin.com/api/ident/linux/{ident}?version=latest"))
|
|
||||||
.send()
|
|
||||||
.await.expect("No future failure");
|
|
||||||
res.json::<IdentResponse>().await.expect("No failure")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
println!("{:?}", find_ident("clear_page_erms").await)
|
let arg_list = args().skip(1);
|
||||||
|
for arg in arg_list {
|
||||||
|
println!("{:=^60}", format!(" {arg} "));
|
||||||
|
show_one_ident(&arg).await;
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||||
|
println!("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn show_one_ident(ident: &str) {
|
||||||
|
let id_resp = ident::find(ident).await;
|
||||||
|
println!("Definitions:");
|
||||||
|
for defs in id_resp.get_definitions() {
|
||||||
|
println!(" - {defs}");
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("References:");
|
||||||
|
for refs in id_resp.get_references() {
|
||||||
|
println!(" - {refs}");
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Documentation:");
|
||||||
|
for docs in id_resp.get_documentations() {
|
||||||
|
println!(" - {docs}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue