Skip to content

Commit

Permalink
Run ChkTeX after saving a document
Browse files Browse the repository at this point in the history
  • Loading branch information
pfoerster committed May 26, 2019
1 parent 2b53f85 commit 2319b11
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 7 deletions.
2 changes: 0 additions & 2 deletions src/diagnostics/build.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use crate::build::log_parser::parse_build_log;
use crate::feature::FeatureRequest;
use crate::workspace::Document;
use lsp_types::{Diagnostic, Uri};
use std::collections::HashMap;
use std::sync::Arc;

#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct BuildDiagnosticsProvider {
Expand Down
88 changes: 88 additions & 0 deletions src/diagnostics/latex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use crate::workspace::Document;
use lazy_static::lazy_static;
use lsp_types::*;
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use std::collections::HashMap;
use std::fs::File;
use std::path::Path;
use std::process::Command;

#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct LatexLinterConfig {
pub on_save: bool,
}

#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct LatexDiagnosticsProvider {
diagnostics_by_uri: HashMap<Uri, Vec<Diagnostic>>,
}

impl LatexDiagnosticsProvider {
pub fn get(&self, document: &Document) -> Vec<Diagnostic> {
match self.diagnostics_by_uri.get(&document.uri) {
Some(diagnostics) => diagnostics.to_owned(),
None => Vec::new(),
}
}

pub fn update(&mut self, uri: &Uri) {
if uri.scheme() != "file" {
return;
}

let path = uri.to_file_path().unwrap();
self.diagnostics_by_uri
.insert(uri.clone(), lint(&path).unwrap_or_default());
}
}

const LINE_PATTERN: &str = "(\\d+):(\\d+):(\\d+):(\\w+):(\\w)+:(.*)";

lazy_static! {
static ref LINE_REGEX: Regex = Regex::new(LINE_PATTERN).unwrap();
}

fn lint(path: &Path) -> Option<Vec<Diagnostic>> {
let file = File::open(path).ok()?;
let output = Command::new("chktex")
.args(&["-I0", "-f%l:%c:%d:%k:%n:%m\n"])
.stdin(file)
.output()
.ok()?;

if !output.status.success() {
return None;
}

let mut diagnostics = Vec::new();
let stdout = String::from_utf8(output.stdout).ok()?;
for line in stdout.lines() {
if let Some(captures) = LINE_REGEX.captures(line) {
let line = captures[1].parse::<u64>().unwrap() - 1;
let character = captures[2].parse::<u64>().unwrap() - 1;
let digit = captures[3].parse::<u64>().unwrap();
let kind = &captures[4];
let code = &captures[5];
let message = captures[6].to_owned();
let range = Range::new_simple(line, character, line, character + digit);
let severity = match kind {
"Message" => DiagnosticSeverity::Information,
"Warning" => DiagnosticSeverity::Warning,
_ => DiagnosticSeverity::Error,
};

diagnostics.push(Diagnostic {
source: Some(Cow::from("chktex")),
code: Some(NumberOrString::String(code.to_owned())),
message: Cow::from(message),
severity: Some(severity),
range,
related_information: None,
})
}
}
Some(diagnostics)
}
9 changes: 7 additions & 2 deletions src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
mod bibtex;
mod build;
mod latex;

use crate::diagnostics::bibtex::BibtexDiagnosticsProvider;
use crate::diagnostics::build::BuildDiagnosticsProvider;
use self::bibtex::BibtexDiagnosticsProvider;
use self::build::BuildDiagnosticsProvider;
use self::latex::LatexDiagnosticsProvider;
pub use self::latex::LatexLinterConfig;
use crate::workspace::Document;
use lsp_types::Diagnostic;

#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct DiagnosticsManager {
pub build: BuildDiagnosticsProvider,
pub latex: LatexDiagnosticsProvider,
pub bibtex: BibtexDiagnosticsProvider,
}

impl DiagnosticsManager {
pub fn get(&self, document: &Document) -> Vec<Diagnostic> {
let mut diagnostics = Vec::new();
diagnostics.append(&mut self.build.get(document));
diagnostics.append(&mut self.latex.get(document));
diagnostics.append(&mut self.bibtex.get(document));
diagnostics
}
Expand Down
1 change: 1 addition & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub enum Event {
Initialized,
WorkspaceChanged,
LogChanged { tex_uri: Uri, log_path: PathBuf },
Saved(Uri),
}

#[derive(Debug, Default)]
Expand Down
16 changes: 13 additions & 3 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::client::LspClient;
use crate::completion::CompletionProvider;
use crate::data::completion::LatexComponentDatabase;
use crate::definition::DefinitionProvider;
use crate::diagnostics::DiagnosticsManager;
use crate::diagnostics::{DiagnosticsManager, LatexLinterConfig};
use crate::event::{Event, EventManager};
use crate::feature::FeatureRequest;
use crate::folding::FoldingProvider;
Expand Down Expand Up @@ -74,7 +74,9 @@ impl<C: LspClient + Send + Sync> LatexLspServer<C> {
change: Some(TextDocumentSyncKind::Full),
will_save: None,
will_save_wait_until: None,
save: None,
save: Some(SaveOptions {
include_text: Some(false),
}),
},
)),
hover_provider: Some(true),
Expand Down Expand Up @@ -158,7 +160,8 @@ impl<C: LspClient + Send + Sync> LatexLspServer<C> {
}

#[jsonrpc_method("textDocument/didSave", kind = "notification")]
pub fn did_save(&self, _params: DidSaveTextDocumentParams) {
pub fn did_save(&self, params: DidSaveTextDocumentParams) {
self.event_manager.push(Event::Saved(params.text_document.uri));
self.event_manager.push(Event::WorkspaceChanged);
}

Expand Down Expand Up @@ -365,6 +368,13 @@ impl<C: LspClient + Send + Sync> jsonrpc::EventHandler for LatexLspServer<C> {
}));
}
}
Event::Saved(uri) => {
let config: LatexLinterConfig = await!(self.configuration("latex.lint"));
if config.on_save {
let mut diagnostics_manager = await!(self.diagnostics_manager.lock());
diagnostics_manager.latex.update(&uri);
}
}
Event::LogChanged { tex_uri, log_path } => {
if let Ok(log) = std::fs::read_to_string(&log_path) {
let mut diagnostics_manager = await!(self.diagnostics_manager.lock());
Expand Down

0 comments on commit 2319b11

Please sign in to comment.