summaryrefslogtreecommitdiff
path: root/scripts/languagetool-flycheck
blob: ecbc900fec8c0924994aceed449ee0eb807edc8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#!/usr/bin/env python3
"""
Wrapper for LanguageTool to produce flycheck-compatible output.
Output format: filename:line:column: message
"""

import json
import sys
import subprocess

def main():
    if len(sys.argv) < 2:
        print("Usage: languagetool-flycheck FILE", file=sys.stderr)
        sys.exit(1)

    filename = sys.argv[1]

    # Run languagetool with JSON output
    try:
        result = subprocess.run(
            ['languagetool', '-l', 'en-US', '--json', filename],
            capture_output=True,
            text=True,
            timeout=30
        )
    except subprocess.TimeoutExpired:
        print(f"{filename}:1:1: LanguageTool timeout", file=sys.stderr)
        sys.exit(1)
    except Exception as e:
        print(f"{filename}:1:1: LanguageTool error: {e}", file=sys.stderr)
        sys.exit(1)

    # Parse JSON output
    try:
        # Find the JSON in the output (skip warning lines)
        json_output = None
        for line in result.stdout.split('\n'):
            if line.startswith('{'):
                json_output = line
                break

        if not json_output:
            sys.exit(0)  # No errors found

        data = json.loads(json_output)

        # Read file to calculate line numbers from character offsets
        with open(filename, 'r', encoding='utf-8') as f:
            content = f.read()

        # Convert matches to flycheck format
        for match in data.get('matches', []):
            offset = match['offset']
            length = match['length']
            message = match['message']
            rule_id = match['rule']['id']

            # Calculate line and column from offset
            line = content[:offset].count('\n') + 1
            line_start = content.rfind('\n', 0, offset) + 1
            column = offset - line_start + 1

            # Get first suggestion if available
            suggestions = match.get('replacements', [])
            if suggestions:
                suggestion = suggestions[0]['value']
                message = f"{rule_id}: {message} Suggestion: {suggestion}"
            else:
                message = f"{rule_id}: {message}"

            # Output in flycheck format
            print(f"{filename}:{line}:{column}: {message}")

    except json.JSONDecodeError as e:
        print(f"{filename}:1:1: Failed to parse LanguageTool JSON: {e}", file=sys.stderr)
        sys.exit(1)
    except Exception as e:
        print(f"{filename}:1:1: Error processing LanguageTool output: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == '__main__':
    main()