Skip to content

chore(lib): continuation of v3 refactor (see #117) #120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Sep 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [3.0.0](https://github.com/jeertmans/languagetool-rust/compare/v2.1.4...v2.1.5)

- Added support for Mardown and Typst files.
- Added support for Markdown and Typst files.
[#117](https://github.com/jeertmans/languagetool-rust/pull/117)

### Chore
### Breaking

- **Breaking** Stopped (de)serializing structs that did not need.
- **Breaking** Stopped (de)serializing structs that did not need it.
[#117](https://github.com/jeertmans/languagetool-rust/pull/117)
- **Breaking** Completly reorganized the crate.
- **Breaking** Completely reorganized the crate.
[#117](https://github.com/jeertmans/languagetool-rust/pull/117)

## [2.1.4](https://github.com/jeertmans/languagetool-rust/compare/v2.1.3...v2.1.4)
Expand Down Expand Up @@ -182,7 +182,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#6](https://github.com/jeertmans/languagetool-rust/pull/6)
- Add compare links to release tags in CHANGELOG.
[#9](https://github.com/jeertmans/languagetool-rust/pull/9)
- Add action to check if can publish.
- Add action to check if crate is publishable.
[#11](https://github.com/jeertmans/languagetool-rust/pull/11)

### Added
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ license = "MIT"
name = "languagetool-rust"
readme = "README.md"
repository = "https://github.com/jeertmans/languagetool-rust"
rust-version = "1.64.0"
rust-version = "1.70.0"
version = "2.1.4"

[package.metadata.docs.rs]
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,14 +153,14 @@ languagetool_rust = "^2.1"
### Example

```rust
use languagetool_rust::{check::CheckRequest, server::ServerClient};
use languagetool_rust::api::{check::CheckRequest, server::ServerClient};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = ServerClient::from_env_or_default();

let req = CheckRequest::default()
.with_text("Some phrase with a smal mistake".to_string()); # codespell:ignore smal
.with_text("Some phrase with a smal mistake".to_string()); //# codespell:ignore smal

println!(
"{}",
Expand Down
16 changes: 8 additions & 8 deletions benches/benchmarks/check_texts.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use criterion::{criterion_group, Criterion, Throughput};
use futures::future::join_all;
use languagetool_rust::{
check::{CheckRequest, CheckResponse, CheckResponseWithContext},
api::{
check::{CheckRequest, CheckResponse, CheckResponseWithContext},
server::ServerClient,
},
error::Error,
server::ServerClient,
};

static FILES: [(&str, &str); 3] = [
Expand Down Expand Up @@ -44,12 +46,10 @@ async fn check_text_split(text: &str) -> CheckResponse {
);
let lines = text.lines();

let resps = join_all(lines.map(|line| {
async {
let req = CheckRequest::default().with_text(line.to_string());
let resp = request_until_success(&req, &client).await;
CheckResponseWithContext::new(req.get_text(), resp)
}
let resps = join_all(lines.map(|line| async {
let req = CheckRequest::default().with_text(line.to_string());
let resp = request_until_success(&req, &client).await;
CheckResponseWithContext::new(req.get_text(), resp)
}))
.await;

Expand Down
32 changes: 17 additions & 15 deletions src/api/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use annotate_snippets::{
use clap::{Args, Parser, ValueEnum};
use serde::{Deserialize, Serialize, Serializer};

use super::error::{Error, Result};
use crate::error::{Error, Result};

/// Requests

Expand All @@ -23,7 +23,7 @@ use super::error::{Error, Result};
/// - a five character string matching pattern `[a-z]{2}-[A-Z]{2}
/// - or some more complex ascii string (see below)
///
/// Language code is case insensitive.
/// Language code is case-insensitive.
///
/// Therefore, a valid language code must match the following:
///
Expand All @@ -38,7 +38,7 @@ use super::error::{Error, Result};
/// # Examples
///
/// ```
/// # use languagetool_rust::check::parse_language_code;
/// # use languagetool_rust::api::check::parse_language_code;
/// assert!(parse_language_code("en").is_ok());
///
/// assert!(parse_language_code("en-US").is_ok());
Expand Down Expand Up @@ -187,7 +187,7 @@ impl DataAnnotation {
#[cfg(test)]
mod data_annotation_tests {

use crate::check::DataAnnotation;
use super::DataAnnotation;

#[test]
fn test_text() {
Expand Down Expand Up @@ -277,7 +277,7 @@ impl Level {
/// # Examples
///
/// ```
/// # use languagetool_rust::check::Level;
/// # use languagetool_rust::api::check::Level;
///
/// let level: Level = Default::default();
///
Expand All @@ -296,7 +296,7 @@ impl Level {
/// # Examples
///
/// ```
/// # use languagetool_rust::check::split_len;
/// # use languagetool_rust::api::check::split_len;
/// let s = "I have so many friends.
/// They are very funny.
/// I think I am very lucky to have them.
Expand Down Expand Up @@ -696,7 +696,7 @@ pub struct CheckCommand {
/// Specify the files type to use the correct parser.
///
/// If set to auto, the type is guessed from the filename extension.
#[clap(long, default_value = "default", ignore_case = true, value_enum)]
#[clap(long, value_enum, default_value_t = FileType::default(), ignore_case = true)]
pub r#type: FileType,
/// Optional filenames from which input is read.
#[arg(conflicts_with_all(["text", "data"]), value_parser = parse_filename)]
Expand All @@ -709,7 +709,7 @@ pub struct CheckCommand {
#[cfg(test)]
mod request_tests {

use crate::CheckRequest;
use super::CheckRequest;

#[test]
fn test_with_text() {
Expand Down Expand Up @@ -845,7 +845,7 @@ pub struct Rule {
pub urls: Option<Vec<Url>>,
}

/// Type of a given match.
/// Type of given match.
#[derive(PartialEq, Eq, Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
Expand Down Expand Up @@ -876,7 +876,7 @@ pub struct Match {
/// More context to match, post-processed using original text.
#[serde(skip_serializing_if = "Option::is_none")]
pub more_context: Option<MoreContext>,
/// Char index at which the match start.
/// Char index at which the match starts.
pub offset: usize,
/// List of possible replacements (if applies).
pub replacements: Vec<Replacement>,
Expand Down Expand Up @@ -959,7 +959,7 @@ impl CheckResponse {
#[must_use]
pub fn annotate(&self, text: &str, origin: Option<&str>, color: bool) -> String {
if self.matches.is_empty() {
return "No error were found in provided text".to_string();
return "No errors were found in provided text".to_string();
}
let replacements: Vec<_> = self
.matches
Expand All @@ -975,8 +975,11 @@ impl CheckResponse {
})
.collect();

let snippets = self.matches.iter().zip(replacements.iter()).map(|(m, r)| {
Snippet {
let snippets = self
.matches
.iter()
.zip(replacements.iter())
.map(|(m, r)| Snippet {
title: Some(Annotation {
label: Some(&m.message),
id: Some(&m.rule.id),
Expand Down Expand Up @@ -1005,8 +1008,7 @@ impl CheckResponse {
color,
..Default::default()
},
}
});
});

let mut annotation = String::new();

Expand Down
3 changes: 0 additions & 3 deletions src/api/languages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

use serde::{Deserialize, Serialize};

/// LanguageTool GET languages request.
pub struct Request;

#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
Expand Down
47 changes: 27 additions & 20 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,64 +1,71 @@
/// Raw bindings to the LanguageTool API v1.1.2.
///
/// The current bindings were generated using the
/// [HTTP API documentation](https://languagetool.org/http-api/).
///
/// Unfortunately, the LanguageTool API is not as documented as we could
/// hope, and resquests might return undocumented fields. Those are deserialized
/// to the `undocumented` field.
//! Raw bindings to the LanguageTool API v1.1.2.
//!
//! The current bindings were generated using the
//! [HTTP API documentation](https://languagetool.org/http-api/).
//!
//! Unfortunately, the LanguageTool API is not as documented as we could
//! hope, and requests might return undocumented fields. Those are de-serialized
//! to the `undocumented` field.
pub mod check;
pub mod languages;
pub mod server;
pub mod words;

/// A HTTP client for making requests to some LanguageTool server.
/// A HTTP client for making requests to a LanguageTool server.
#[derive(Debug)]
pub struct Client {
/// Server's hostname.
hostname: String,
/// Server's port.
port: Option<String>,
/// Inner client to perform HTTP requets.
/// Inner client to perform HTTP requests.
client: reqwest::Client,
}

impl Default for Client {
fn default() -> Self {
Self {
hostname: "https://api.languagetoolplus.com".to_string(),
..Default::default()
port: None,
client: Default::default(),
}
}
}

impl Client {
/// Construct a HTTP url base on the current hostname, optional port,
/// Construct an HTTP URL base on the current hostname, optional port,
/// and provided endpoint.
#[inline]
#[must_use]
pub fn url(&self, endpoint: &str) -> String {
let hostname = self.hostname;
match self.port {
let hostname = &self.hostname;
match &self.port {
Some(p) => format!("{hostname}:{p}/v2{endpoint}"),
None => format!("{hostname}/v2{endpoint}"),
}
}

/// Send a check request to the server and await for the response.
pub async fn check(&self, request: &check::Request) -> Result<check::Response> {
pub async fn check(
&self,
request: &check::CheckRequest,
) -> reqwest::Result<check::CheckResponse> {
self.client
.post(self.url("/check"))
.query(request)
.send()
.await?
.json::<check::Response>()
.json::<check::CheckResponse>()
.await
}

/// Send a words request to the server and await for the response.
pub async fn languages(&self, request: &languages::Request) -> Result<languages::Response> {
/// Send a request for the list of supported languages to the server and await for the response.
pub async fn languages(&self) -> reqwest::Result<languages::Response> {
self.client
.get(self.url("/languages"))
.query(request)
.send()
.await?
.json::<check::Response>()
.json::<languages::Response>()
.await
}
}
Loading
Loading