news 2026/10/23 3:19:49

QOwnNotes 离线语法与风格检查:Harper 集成完整配置指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
QOwnNotes 离线语法与风格检查:Harper 集成完整配置指南
  • 桌面应用

【免费下载链接】QOwnNotes

QOwnNotes is a plain-text file notepad and todo-list manager with Markdown support and Nextcloud / ownCloud integration.

项目地址:https://gitcode.com/gh_mirrors/qo/QOwnNotes
点击查看免费下载

QOwnNotes 通过内置的 Harper 支持,在笔记编辑器中提供可选的离线语法与风格检查(offline grammar and style checking),基于harper-ls语言服务器在本地完成检测,无需把笔记内容发送到任何外部服务。本文将带你完成 Harper 的启用、运输方式(Transport)选择、方言与 Linter 配置、连接测试,并从源码层面剖析它的工作机理,帮助你把这套检查能力无缝接入自己的写作流程。

Harper 与现有拼写检查的关系

Harper 并不是用来替代 QOwnNotes 原有拼写检查(spellchecking)的,而是作为其补充:拼写检查负责基础拼写纠错,Harper 更进一步覆盖语法、风格、标点与措辞层面的问题。在 README 中,QOwnNotes 将 Harper 与 LanguageTool、Markdown LSP 并列介绍,三者同属于编辑器可选的语法/风格检查能力。

核心功能

根据 Harper 文档 与源码实现,该功能包含以下能力:

  • 彩色下划线标注:语法、风格、标点、措辞问题按类别用不同颜色显示在编辑器内;
  • 右键菜单替换建议:右键点击问题文本即可看到候选替换词;
  • 忽略机制:支持Ignore this rule(忽略某条规则)与Ignore word(忽略某个单词)操作;
  • 快速开关:Edit(编辑)菜单提供Check grammar with Harper切换项;
  • 完全本地检查:通过harper-ls语言服务器以Stdio或TCP方式通信,全程无需联网。

设置步骤

打开 QOwnNotes 的Settings(设置),选择Editor -> Harper,即可看到 harpersettingswidget.ui 中定义的完整配置界面。

1. 启用功能

勾选Enable offline grammar and style checking with Harper(启用 Harper 离线语法与风格检查)。该开关对应设置键harperEnabled,默认值为false,源码中由 harperchecker.cpp 的readSettings()读取。同时,Edit菜单中的Check grammar with Harper动作(见 mainwindow.ui)也会同步该开关状态,具体逻辑位于 mainwindow.cpp。

2. 选择运输方式(Transport)

选项说明默认值
Stdio (recommended)由 QOwnNotes 直接启动本地harper-ls进程(对应模式值 0)推荐
TCP连接一个已经运行的harper-ls服务器(对应模式值 1)—

运输方式保存在设置键harperTransportMode中。源码层面,harperclient.cpp 的ensureTransport()根据模式分别创建HarperStdioTransport(基于QProcess)或HarperTcpTransport(基于QTcpSocket)两种传输实现。

Stdio 模式参数
  • Command / binary path(命令/二进制路径):默认命令为harper-ls,对应设置键harperBinaryPath;
  • Auto-detect(自动检测):通过QStandardPaths::findExecutable在系统PATH中查找harper-ls(见 harpersettingswidget.cpp),找到后会把完整路径回填到输入框;
  • Browse(浏览):手动选择 Harper 可执行文件。

启动时,Stdio 传输会以harper-ls --stdio参数拉起子进程,并等待最多 2 秒确认启动成功(harperclient.cpp)。

TCP 模式参数
  • Server address(服务器地址):默认127.0.0.1,对应设置键harperTcpAddress;
  • Port(端口):默认4000,对应设置键harperTcpPort,UI 中允许的范围为 1~65535。

TCP 连接等待超时同为 2 秒;连接失败时会记录下一次重试时间(当前实现为失败后等待 2 秒再重连,见ensureStarted())。

3. 选择方言(Dialect)

Dialect下拉框提供 5 种英语方言选项:

  • American(美式,默认)
  • British(英式)
  • Australian(澳式)
  • Canadian(加式)
  • Indian(印式)

方言值保存在harperDialect中,会作为dialect字段写入发送给harper-ls的配置(harperclient.cpp)。

4. 调整检查延迟(Check delay)

Check delay(检查延迟)控制 QOwnNotes 在停止输入后、发起检查请求前等待的毫秒数。UI 中可调范围为500~5000 ms,步长 100 ms,默认 1500 ms(对应设置键harperCheckDelay)。底层通过单次定时器QTimer实现防抖(debounce),并在设置读取时把定时器间隔同步为该值(harperchecker.cpp)。

5. 选择启用的 Linter

以下 12 个 Linter 均可独立勾选(源码中的内部标识见括号):

UI 名称内部标识
Spell Check(拼写检查)SpellCheck
Sentence Capitalization(句首大写)SentenceCapitalization
Repeated Words(重复单词)RepeatedWords
Long Sentences(长句)LongSentences
An vs A(冠词 a/an 选择)AnA
Unclosed Quotes(未闭合引号)UnclosedQuotes
Correct Number Suffix(数字后缀纠正)CorrectNumberSuffix
Spaces(空格)Spaces
Quote Spacing(引号间距)QuoteSpacing
No French Spaces(无法语空格)NoFrenchSpaces
Wrong Apostrophe(错误撇号)WrongApostrophe
Spelled Numbers(拼写数字)SpelledNumbers

默认启用SpellCheck、AnA、SentenceCapitalization、RepeatedWords、LongSentences、Spaces、QuoteSpacing、NoFrenchSpaces、WrongApostrophe、CorrectNumberSuffix、UnclosedQuotes这 11 项(SpelledNumbers默认关闭),完整默认列表见 harperchecker.cpp。勾选结果保存在harperEnabledLinters中,并在发送配置时以布尔开关形式写入 LSP 的linters配置对象。

6. 测试连接

点击Test Connection按钮验证配置是否可用:

  • Stdio 模式下会尝试启动harper-ls;
  • TCP 模式下会尝试连接配置的服务器;
  • 测试时会发送一段固定测试文本"This are a test sentence."(harpersettingswidget.cpp),收到checkFinished信号则弹窗提示连接成功,并附带服务器版本号;收到checkError则提示连接失败原因。

页面底部还有一个Status状态区:Stdio 模式下会显示找到的harper-ls路径与版本(通过执行harper-ls --version查询),TCP 模式下显示目标地址与端口。

7. 管理忽略项

设置页提供两个重置按钮:

  • Reset ignored rules(重置忽略的规则):清除所有通过右键菜单Ignore this rule忽略的规则;
  • Reset ignored words(重置忽略的单词):清除所有通过右键菜单Ignore word忽略的单词。

两者点击后均会弹出确认对话框。忽略的规则保存在harperIgnoredRules、忽略的单词保存在harperIgnoredWords中。值得注意的是,忽略单词时不仅会记录到 Harper 自己的集合,还会同步调用QOwnSpellChecker把该词加入系统拼写词典(harperchecker.cpp)。

工作原理

Harper 在 QOwnNotes 中的工作流程由三个核心组件协作完成,全部位于 services 目录:

  • HarperChecker(harperchecker.h / harperchecker.cpp):编辑器侧的调度器,负责决定检查哪些内容、何时发起请求、缓存与管理忽略项;
  • HarperClient(harperclient.h / harperclient.cpp):LSP 客户端,负责与harper-ls的协议通信;
  • HarperMatch(harpertypes.h):表示单个检查结果的数据结构,包含偏移量、长度、消息、规则 ID、规则类别、替换建议与上下文文本。

只检查可见区块

QOwnNotes 不会把整篇文档一次性发给 Harper,而是通过visibleBlocks()计算当前视口(viewport)内可见的文本块(harperchecker.cpp)。滚动编辑器时也会触发重新调度(监听垂直滚动条的valueChanged)。

跳过无关内容

shouldCheckBlock()会跳过以下类型的文本块(harperchecker.cpp):

  • 不可见或无效的块;
  • 空白行(trim 后为空);
  • 标题行(HeadlineEnd状态);
  • 代码块(CodeBlock状态,以及 MarkdownHighlighter 中CodeCpp之后的所有代码状态)。

防抖与缓存

  • 防抖:每次文本变化只启动单次定时器,间隔即设置中的Check delay,避免每敲一个键就发一次请求;
  • 区块级缓存:每个文本块以其 SHA-1 哈希作为键缓存结果,内容未变化时直接复用;缓存条目默认 TTL 为 300 秒、上限 500 条,过期与超限条目会被清理(cleanupExpiredCache()与enforceCacheLimit());
  • 结果有效性校验:请求返回时会重新计算文档 SHA-1,与提交时记录的哈希比对,若文档在请求期间被修改则丢弃过期结果(handleRequestFinished())。

LSP 协议通信细节

HarperClient 实现了标准的 Language Server Protocol(LSP)2.0 流程,包括:

  • 初始化握手(initialize/initialized),并声明textDocument/codeAction与workspace/configuration能力;
  • 通过workspace/didChangeConfiguration下发方言与 Linter 配置;
  • 用textDocument/didOpen打开一个虚拟 Markdown 文档(URI 形如file:///qownnotes-harper-<id>.md,languageId 为markdown);
  • 接收textDocument/publishDiagnostics通知,将行/列坐标换算为绝对偏移,构造HarperMatch;
  • 对每个诊断发起textDocument/codeAction请求,从返回结果中解析Replace with: "..."形式的替换建议(decodeReplacementTitle())以及 workspace edit 中的newText;
  • 所有请求带 5 秒超时,超时或服务异常时通过checkError信号通知上层。

问题高亮与右键菜单

  • 着色:QOwnNotesMarkdownHighlighter的highlightHarper()(qownnotesmarkdownhighlighter.cpp)根据ruleCategory决定下划线颜色:
    • Spelling(拼写)→ 红色;
    • Style(风格)→ 琥珀色#c99500;
    • Punctuation(标点)→ 绿色#1c8f47;
    • Typography(排版)→ 紫色#7a3db8;
    • 其余(默认 Grammar 语法类)→ 蓝色#2a6fdb。 高亮采用SpellCheckUnderline波浪下划线样式,并附带问题消息作为 tooltip。
  • 右键菜单:addHarperMenuSection()(qownnotesmarkdowntextedit.cpp)在光标位置命中问题时会弹出菜单,包含:类别与规则名(不可点击的头部)、最多 8 条替换建议、Ignore this rule、Ignore word "..."。选择替换建议后通过applyHarperReplacement()以对应位置范围直接替换文本。

不可用时的降级行为

如果 Harper 无法启动或连接(如harper-ls未安装),QOwnNotes 会在状态栏显示带警告图标的提示消息(持续约 5 秒),并通过connectionError信号通知,随后停止检查直到服务恢复可用(harperchecker.cpp)。

构建前提

Harper 支持是可选的,取决于构建时是否启用该特性:

  • CMake 构建:src/CMakeLists.txt中定义HARPER_ENABLED选项,默认ON(src/CMakeLists.txt),启用后通过target_compile_definitions(... HARPER_ENABLED)传入编译器;
  • qmake 构建:对应源码文件在 src/QOwnNotes.pro 中登记。

若构建未启用该特性,Settings -> Editor -> Harper页面会显示"Harper support is not available in this build.",且所有选项不可用;Edit菜单中的Check grammar with Harper动作也会被隐藏(mainwindow.cpp)。

与 LanguageTool 的关系

Harper 与 LanguageTool 可以同时启用。两者的定位差异在于:

  • LanguageTool:既可连接本地自托管服务,也可连接远程服务(如http://localhost:8081或https://api.languagetoolplus.com),并支持按 Spelling/Grammar/Style/Punctuation/Typography 类别勾选;
  • Harper:主打完全本地离线,通过harper-ls以 Stdio 或 TCP 方式工作,无需配置任何远程 URL。

在实现上二者相互独立(分别由LANGUAGETOOL_ENABLED与HARPER_ENABLED编译开关控制),高亮渲染也走各自的管线,因此可以放心叠加使用。

常见问题

  • harper-ls没有找到?先确认已安装 Harper 命令行工具并使其位于PATH中,然后点击设置页的Auto-detect;或使用Browse手动指定可执行文件路径。
  • TCP 连接失败?确认harper-ls已以 TCP 服务方式启动、地址端口与设置一致(默认127.0.0.1:4000),再用Test Connection验证。
  • 修改配置后不生效?HarperChecker 的scheduleCheck()每次触发前都会调用readSettings()重新读取设置,因此改动保存后会在下一次检查时自动生效。
  • 检查结果没有出现?确认已勾选启用开关、对应的 Linter 处于开启状态,并且光标所在文本块不是标题或代码块(这些内容会被有意跳过)。

相关文档

  • 拼写检查
  • LanguageTool 语法与风格检查
  • Markdown LSP
  • QOwnNotes 核心概念
  • 桌面应用

【免费下载链接】QOwnNotes

QOwnNotes is a plain-text file notepad and todo-list manager with Markdown support and Nextcloud / ownCloud integration.

项目地址:https://gitcode.com/gh_mirrors/qo/QOwnNotes
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 9:51:38

bbox实战:解决多栏PDF与扫描水印的文档解析难题

1. 为什么 bbox 能治多栏排版和水印 PDF 的“病”先交代一下背景。我在给 RAG 知识库做文档解析时&#xff0c;最头疼的输入不是那种干净的单栏 PDF&#xff0c;而是两类“刺头”&#xff1a;一类是学术论文、财报、报纸截图导出的多栏排版 PDF&#xff0c;一类是带各种水印的扫…

作者头像 李华
网站建设 2026/10/21 17:32:27

Vue3+Three.js创建会议室三维模型:从建模到性能优化实战

前段时间帮某企业做一个智慧园区的数字孪生项目&#xff0c;对方提了个特别具体的需求&#xff1a;把整层会议室的真实布局搬进网页&#xff0c;人不在现场也能查看房间结构、设备位置和占用状态。当时我几乎没有犹豫就选了VUETHREEJS 创建完整会议室三维模型这条路。折腾了两周…

作者头像 李华
网站建设 2026/10/18 13:37:25

MFC多边形扫描转换原理与AET实现详解

1. 项目概述&#xff1a;为什么在MFC里做多边形扫描转换&#xff0c;至今仍是图形学教学的“硬核试金石”“计算机图形学 实验4 多边形的扫描转换&#xff08;MFC中&#xff09;”——这个标题一出来&#xff0c;我眼前就浮现出某高校图形学实验室里&#xff0c;十几台老式台式…

作者头像 李华
网站建设 2026/10/18 3:25:15

Sandbox 隔离哪些资源?

第203题&#xff1a;Sandbox 隔离哪些资源&#xff1f;1. 核心回答 对于执行不可信代码的 Sandbox&#xff0c;我会至少隔离六类资源&#xff1a; 文件系统进程网络身份与凭据CPU、内存、进程数和执行时间系统调用与内核攻击面 实际工程中还会进一步限制设备、IPC、磁盘写入和输…

作者头像 李华