BigMarc 3ea090ae4b Embed the real Harper grammar core via Rust C-FFI
Replace the NSSpellChecker + regex-stub engine with harper-core 2.5.0:
real subject-verb agreement, verb forms, punctuation, repetition and
spelling. New harper-ffi crate (staticlib) exposes harper_check over a C
ABI; the CHarper module bridges it to Swift; HarperEngine maps Harper's
char spans onto UTF-16 ranges and de-dups overlapping lints. NSSpellChecker
stays only as a case-preserving spelling supplement, which fixes the
problemm->Problem mis-casing. Bulk apply now skips no-op suggestions.

build.sh / scripts/build.sh build the universal static lib; target/ and
lib/ are gitignored (regenerate via harper-ffi/build.sh).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 06:43:11 +02:00

57 lines
1.7 KiB
C

/*
* harper.h — C ABI for the harper-ffi static library (harper-core 2.5.0).
*
* Link against libharper_ffi.a. All strings are UTF-8.
*/
#ifndef HARPER_FFI_H
#define HARPER_FFI_H
#ifdef __cplusplus
extern "C" {
#endif
/*
* Check `text` for grammar/spelling issues using harper-core.
*
* Returns a malloc'd, NUL-terminated UTF-8 JSON C string that the caller MUST
* free with harper_free().
*
* The JSON is an array of objects:
* [
* {
* "start": <integer, char (Unicode scalar) offset into the input>,
* "len": <integer, char count of the offending span>,
* "replacement": "<string>",
* "message": "<string>",
* "kind": "<string>"
* },
* ...
* ]
*
* Notes on the contract:
* - "start"/"len" are CHAR (Unicode scalar) offsets, matching harper's native
* char indexing. They are NOT byte offsets and NOT UTF-16 code-unit offsets.
* "len" = span.end - span.start (end-exclusive).
* - "replacement" is the FIRST ReplaceWith suggestion's text. If the first
* actionable suggestion is a removal, "replacement" is "" (empty string).
* - Lints with NO actionable suggestion are SKIPPED.
* - "kind" is one of: "spelling", "grammar", "punctuation", "repetition",
* "capitalization", "phrasing". Best-effort; defaults to "grammar".
*
* On a null `text`, invalid UTF-8, or any internal error/panic, returns "[]".
* Never returns NULL on a normal return path. Thread-safe.
*/
char *harper_check(const char *text);
/*
* Free a string previously returned by harper_check().
* Passing NULL is a no-op. Do not free the same pointer twice.
*/
void harper_free(char *ptr);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* HARPER_FFI_H */