# HiTikZ **Repository Path**: ylxdxx/HiTikZ ## Basic Information - **Project Name**: HiTikZ - **Description**: TikZ 代码管理 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-04 - **Last Updated**: 2026-08-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # HiTikZ — TikZ 代码合集管理器 > 面向 Linux (KDE 6 / Wayland) 的 TikZ/PGF 矢量图形管理工具。 > 创建、编辑、预览、搜索、导出 TikZ 图像并支持批量操作。 ![Screenshot](Screenshot.png) --- ## 目录 - [功能概览](#功能概览) - [系统要求](#系统要求) - [快速开始](#快速开始) - [用户界面](#用户界面) - [核心功能说明](#核心功能说明) - [片段管理](#片段管理) - [分类系统](#分类系统) - [模糊搜索](#模糊搜索) - [代码编辑器](#代码编辑器) - [代码补全](#代码补全) - [LaTeX 编译与 PDF 预览](#latex-编译与-pdf-预览) - [参数化系统](#参数化系统) - [自动保存与草稿恢复](#自动保存与草稿恢复) - [模板系统](#模板系统) - [宏包与 TikZ 库](#宏包与-tikz-库) - [自定义命令处理](#自定义命令处理) - [完整文档复制](#完整文档复制) - [文档元数据注释](#文档元数据注释) - [多选与批量操作](#多选与批量操作) - [剪贴板操作](#剪贴板操作) - [导入与导出](#导入与导出) - [图片管理](#图片管理) - [复制链接](#复制链接) - [打包链接图片到项目(命令行 pack)](#打包链接图片到项目命令行-pack) - [键盘快捷键](#键盘快捷键) - [预置片段清单](#预置片段清单) - [数据存储](#数据存储) - [设置面板](#设置面板) - [命令行构建](#命令行构建) - [项目架构](#项目架构) - [测试](#测试) - [技术栈](#技术栈) - [已知问题](#已知问题) --- ## 功能概览 HiTikZ 以「片段(snippet)」为核心概念组织 TikZ 代码。每个片段是一段独立的 TikZ 代码及其元数据,涵盖名称、简介、分类、标签、宏包、TikZ 库、编译命令和模板等信息。以下按功能领域概述主要能力,详细说明见[核心功能说明](#核心功能说明)。 ### 片段与内容管理 提供完整的 TikZ 代码生命周期管理,支持创建、编辑、保存、删除片段。每个片段可附带名称、简介、分类、标签、宏包、TikZ 库、自定义编译命令、模板等元数据。 内置层级分类系统(如 `数学/几何`),支持空分类独立存在,分类树下直接显示所属片段名称。拖拽片段到分类节点即可重新归类,拖拽排序自动持久化,新建片段默认排列在所属分类最前。通过 Ctrl+点击可多选缩略图或分类节点,右键菜单提供复制、删除、批量导出等批量操作。右键单个缩略图弹出属性对话框,可编辑全部元数据字段(含自定义编译引擎)并管理片段图片(导入/粘贴/查看/替换/删除,见[图片管理](#图片管理))。 模糊搜索基于 Unicode 子序列匹配,配合双字倒排索引加速,按名称与简介双向搜索,连续匹配得分更高。搜索框下方自动展示所有标签徽章,点击即可按标签筛选(多标签 AND 组合)。标签数量较多时自动折叠为两行并支持弹窗浏览。增删标签后标签栏即时刷新:新标签自动出现,不再使用的标签自动消失并同步取消筛选;标签集合不变时标签栏保持稳定不闪烁。 工具栏支持复制当前片段;右键缩略图或分类树片段节点可后台复制,无需切换编辑器。 ### 代码编辑器 采用多标签页设计,可同时打开多个片段并自由切换,重复打开同一片段自动激活已有标签页。每个标签页的元数据相互隔离,切换时不会相互干扰。 编辑器提供 TikZ/LaTeX 彩色语法高亮,包含 14 条正则规则与跨行选项括号处理,以及 6 类用户定义名称识别。key=value 分色显示且花括号深度感知,支持跨行选项列表与 `\begin{comment}` 多行注释块。光标置于某单词或双击选中时,文档中所有相同单词自动高亮,便于追踪变量与命令。 智能代码补全覆盖 TikZ/PGF 及多个专业绘图宏包,支持 13 种上下文与三级过滤,并自动纳入用户定义的样式、坐标、命令等(详见[代码补全](#代码补全))。`\begin{env}` 补全后自动插入 `\end{env}`。 编辑器支持自动缩进、块缩进与反缩进(Tab/Shift+Tab)、括号自动配对(`{}`、`[]`、`()`、`$` 及行内公式 `$…$`)、空括号对退格删除等常见编辑操作。括号配对高亮为可选功能(默认关闭),开启后光标在括号旁时高亮匹配的括号对(蓝色背景),找不到配对以红色警示,支持跨行嵌套和混合类型。过长行自动换行为可选功能(默认开启),续行在行号栏以 `↳` 标记。支持标准 Ctrl+Z 撤销与 Ctrl+Shift+Z 重做。 ### 编译与预览 默认调用 `xelatex -shell-escape` 编译,QPdfView 渲染高清 PDF 矢量预览。每个片段可独立指定编译引擎与参数(XeLaTeX、LuaLaTeX、PdfLaTeX)。遇到死循环代码可随时通过工具栏「强制结束」按钮中断编译。 编译日志精简显示,仅呈现编译命令、错误(带上下文)与警告,过滤文件加载等噪音行。错误行号自动映射到编辑器行号并支持双击跳转。 PDF 预览支持适应整页、适应宽度、适应高度三种缩放模式,滚轮以鼠标位置为中心缩放,左键拖拽平移。重新编译后保持视口位置,便于对比修改前后的细节变化。编译成功后 PDF 与缩略图 PNG 自动持久化,切换片段即时展示。 设置面板提供「生成所有预览」功能,多线程并行编译所有片段(线程数可调,默认 6),完成后弹出成功与失败统计报告。 ### 参数化与文档组织 通过 `% @param: var=默认值` 声明参数变量,以 `@@var@@` 作为占位符,右栏自动生成参数输入控件。编辑器内输入 `@@` 可触发参数名补全。 三个内置极简 LaTeX 模板(数学、物理、电路),仅含必要宏包,额外宏包与 TikZ 库由每个片段自行声明。每个片段可指定额外 `\usepackage` 宏包与 `\usetikzlibrary` 库,编译时自动注入导言区。右下角「额外宏包」「TikZ库」两栏均支持逗号感知的名称自动补全,库栏改动即时同步到编辑器补全(无需在代码里写 `\usetikzlibrary`)。 代码中的自定义定义命令(`\newcommand`、`\NewDocumentCommand`、`\tikzset`、`\definecolor`、`\pgfmathsetmacro` 等约 40 类)会被自动识别并抽取,在编译和复制文档时注入导言区。 ### 导入、导出与剪贴板 片段以 tar.gz 格式打包,支持单个、多个或全部片段的导出与导入。支持导入 .tex 文件,自动提取 TikZ 代码(三段式回退)并解析导言区宏包、库与自定义命令,按内容自动选择模板。支持从剪贴板直接粘贴 .tex 源码导入,解析流程同上。 可将预览导出为 .tex、.pdf、.png、.svg 文件,或将 PNG、SVG 复制到剪贴板。工具栏提供「复制代码」「复制文档」「复制 PNG」「复制 SVG」快捷按钮。新增「复制文件」功能,将完整可编译的 .tex 文档与编译 PDF(含片段图片)一同放入剪贴板(命名为 `000.tex` / `000.pdf`),在 Dolphin 文件管理器中直接 Ctrl+V 即可粘贴分享。新增「复制链接」功能,把当前片段编译 PDF 以序号文件名(`0001.pdf`、`0002.pdf`…)链接到指定目录(默认 `~/PicTikZ`),并将 `\includegraphics{~/PicTikZ/0001.pdf}` 复制到剪贴板,直接粘贴进课件等 LaTeX 项目即可引用;片段重新编译后图片自动更新,插图制作与文档写作彻底分离(见[复制链接](#复制链接))。分享文档项目时,命令行 `hitikz pack` 读取文档引用、把**用到的**链接图片按需复制进项目目录并把 `.tex` 引用改为新路径(未引用的图片不动),也可同时附带完整源码(见[打包链接图片到项目](#打包链接图片到项目命令行-pack))。复制文档 / 复制文件 / 导出 .tex 生成的完整文档以注释形式携带片段名称、简介、标签,导入时自动解析还原(见[文档元数据注释](#文档元数据注释))。 ### 数据安全与恢复 每 3 分钟自动保存所有打开标签页的完整状态为 JSON 草稿。异常退出后重启时自动弹出恢复对话框,列出未保存草稿供勾选恢复或丢弃。关闭标签页或退出程序时自动检查未保存更改。 ### 系统集成与个性化 支持最小化到系统托盘,通过全局快捷键一键呼出或隐藏。开机自启动可在设置面板一键开启,启动后静默驻留托盘,登录后不弹出主窗口。全部快捷键支持自定义键序列,支持清空禁用。KDE 桌面通过 KGlobalAccel 注册系统级快捷键。 代码编辑器字体与全局界面字体大小可分别调节(均 8–48 pt)。启动时自动检测 XeLaTeX 与当前 SVG 转换工具,缺失时弹出安装指引。 ### 内容与实现 内置 120 个高质量预置片段,涵盖数学、物理、电路、化学等领域,均从 tikz.net 和 TeXample.net 精选并经 XeLaTeX 编译验证。程序采用 C++17 + Qt6 原生实现,高性能启动,原生 Wayland 支持。 --- ## 系统要求 | 依赖 | 版本 / 说明 | |------|------------| | **操作系统** | Linux(主力支持 KDE 6 / Wayland) | | **C++ 编译器** | GCC 11+ 或 Clang 14+(C++17) | | **CMake** | 3.16+ | | **Qt6** | Widgets、Pdf、PdfWidgets 模块 | | **KF6GlobalAccel** | (可选)KDE 原生全局快捷键 | | **QHotkey** | 通过 CMake FetchContent 自动拉取(KF6GlobalAccel 不可用时的回退) | | **XeLaTeX** | TeX Live 2023+(或等效发行版) | | **pdftocairo** | poppler 工具集(默认 SVG 转换工具) | | **Inkscape** | (可选)备选 SVG 转换工具,在设置面板中切换 | | **tar** | GNU tar(用于导入/导出存档) | | **unzip** | (可选)导入 .zip 格式存档时的回退工具 | ## 依赖安装指南 ### Arch / Manjaro ```bash sudo pacman -S --needed base-devel cmake git \ qt6-base qt6-webengine qt6-tools \ extra-cmake-modules kglobalaccel ``` > **注意**:如果 `kglobalaccel` 包未提供 KF6 版本,可尝试安装 `kglobalaccel6`。当前 Arch 滚动更新,`kglobalaccel` 已默认提供 KF6。 --- ### Debian / Ubuntu > **前置条件**:需要 **Debian Trixie (13)+** 或 **Ubuntu 24.04+**,较低版本可能缺少 `qt6-pdf-dev` 或 `libkf6globalaccel-dev`。 ```bash sudo apt update sudo apt install -y build-essential cmake git pkg-config \ qt6-base-dev qt6-pdf-dev qt6-tools-dev \ extra-cmake-modules libkf6globalaccel-dev ``` > **如果 `qt6-pdf-dev` 不存在**(较旧系统),可改用 PPA: > ```bash > sudo add-apt-repository ppa:okirby/qt6-backports > sudo apt update > sudo apt install qt6-pdf-dev > ``` --- ### Fedora > **前置条件**:建议 **Fedora 40+**(KF6 和 Qt6 PDF 模块完整可用)。 ```bash sudo dnf install -y cmake git gcc-c++ make pkgconf-pkg-config \ qt6-qtbase-devel qt6-qtpdf-devel qt6-qttools-devel \ extra-cmake-modules kf6-kglobalaccel-devel ``` --- ### 构建步骤(通用) ```bash # 克隆项目 git clone https://gitee.com/ylxdxx/HiTikZ.git #国内 git clone https://github.com/YLXDXX/HiTikZ.git #国外 cd HiTikZ # 构建 cmake -B build cmake --build build -j$(nproc) # 直接从构建目录运行(无需安装) ./build/hitikz # 运行测试 cd build && ctest --output-on-failure ``` > 可执行程序名为全小写的 **`hitikz`**。直接从构建目录运行时,程序会自动使用源码树内的 `resources/`;安装后则使用安装目录中的资源。 如需禁用 KGlobalAccel(仅用 QHotkey 后备方案): ```bash cmake -B build -DWITH_KGLOBALACCEL=OFF ``` 如需同时禁用全局快捷键: ```bash cmake -B build -DWITH_KGLOBALACCEL=OFF -DWITH_QHOTKEY=OFF ``` --- ### 安装与卸载 遵循 Linux 目录惯例:用户自行编译的程序默认安装到 **`/usr/local`**(可通过 `CMAKE_INSTALL_PREFIX` 或 `--prefix` 自定义)。 ```bash # 安装(默认前缀 /usr/local,需要写入系统目录故用 sudo) sudo cmake --install build # 指定安装前缀(例如系统级 /usr) cmake --install build --prefix /usr # 卸载(依据安装时生成的 install_manifest.txt 移除已安装文件) sudo cmake --build build --target uninstall ``` 安装内容与目标位置(以默认前缀 `/usr/local` 为例): | 文件 | 安装位置 | |------|---------| | 可执行程序 `hitikz` | `/usr/local/bin/` | | 预置片段与模板 `resources/` | `/usr/local/share/hitikz/resources/` | | 桌面入口 `hitikz.desktop` | `/usr/local/share/applications/` | | 应用图标 `hitikz.svg` | `/usr/local/share/icons/hicolor/scalable/apps/` | > **打包用途**:安装步骤支持 `DESTDIR`(如 `DESTDIR=/tmp/stage cmake --install build`),便于制作发行版软件包。 > **版本号**:版本号在 `CMakeLists.txt` 的 `project(... VERSION x.y)` 处**统一设定**,经编译宏 `APP_VERSION` 传入程序(`main.cpp` 不再硬编码版本号),后续升级只需修改这一处。 --- ### 运行时依赖(非构建依赖) 运行时需要 LaTeX 发行版: | 发行版 | 安装命令 | | --------------- | ------------------------------------------------------------ | | Arch / Manjaro | `sudo pacman -S texlive` | | Debian / Ubuntu | `sudo apt install texlive texlive-latex-extra texlive-pictures` | | Fedora | `sudo dnf install texlive-scheme-medium texlive-pictures` | PDF 预览依赖 `Qt6::PdfWidgets`,已在构建依赖中包含,无需额外运行时安装。 ## 用户界面 程序采用经典三栏布局,全栏宽度可拖动调整,右侧 PDF 预览与元数据区可上下拖动分割条。 ### 工具栏 按从左到右顺序: | 按钮 | 功能 | |------|------| | 新建片段 | 弹出对话框输入名称、分类和模板(默认 `default_math`) | | 删除片段 | 删除当前片段或分类 | | 复制片段 | 复制当前片段的所有内容(代码、元数据、标签、图片等),新片段使用相同标题 | | 导入/导出 ▼ | 下拉菜单:导入存档 / 导入 .tex 文件 / 从剪贴板导入 / 导出当前 / 导出全部 / 导出为 Tex 文档 / 导出为 PDF 文档 / 导出为 PNG 图片 / 导出为 SVG 图片 | | 撤销 / 重做 | 撤销(Ctrl+Z)/ 重做(Ctrl+Shift+Z);历史可用时才可点击 | | 编译预览 | 保存并编译 TikZ 代码渲染 PDF(自动应用参数替换) | | 应用参数 | 不保存,仅用参数值替换后编译(用于临时预览参数效果) | | 保存 | 保存当前片段(若在设置中开启"保存后自动编译",则保存后自动触发编译) | | 强制结束 | 强制中断正在进行的编译或批量生成(死循环 TikZ 代码 / 编译卡死时使用) | | 复制代码 | 复制参数替换后的 TikZ 核心代码 | | 复制文档 | 复制含模板头部的完整 LaTeX 文档 | | 复制PNG | 复制 300 DPI PNG 到剪贴板 | | 复制SVG | 复制 SVG 到剪贴板 | | 复制链接 | 将当前片段编译 PDF 链接到图片目录(默认 `~/PicTikZ`,序号命名 `0001.pdf`、`0002.pdf`…),复制 `\includegraphics{...}` 引用命令到剪贴板(见[复制链接](#复制链接)) | | 复制文件 | 复制完整可编译 .tex 文档与 PDF 到剪贴板(000.tex / 000.pdf,含片段图片),可在文件管理器中直接粘贴 | | 外部PDF | 用设置中配置的外部查看器打开当前片段的编译 PDF(系统需先编译预览) | | 适应整页/宽度/高度 | PDF 显示模式(可选中态) | | − / + | PDF 缩小/放大 | | 设置 | 打开设置面板 | ### 左栏 - **搜索框**:输入关键词实时搜索,按名称与简介模糊匹配 - **标签过滤器**:搜索框下方的流式布局标签徽章,点击标签筛选片段(AND 逻辑),选中标签蓝色高亮。标签过多时自动折叠为最多两行,调整窗口宽度时保持稳定,点击「更多标签...」弹出对话框展示全部标签。标签栏随增删片段操作即时刷新:新标签自动出现,不再被任何片段使用的标签自动消失;若当前选中的标签被移除,则自动取消选中并重新过滤。标签栏仅在标签集合真正变化时重建——保存时若标签未变则保持折叠状态,不会闪烁 - **分类树**:层级分类导航,节点显示片段数量,点击分类过滤缩略图列表 - 含"全部"和"未分类"两个特殊节点 - 空分类可独立存在(通过 `category_list.json` 持久化),删除最后片段不再自动删除分类 - 每个分类节点下直接显示属于该分类(而非子分类)的片段名称,方便区分直属片段与子分类内容 - **Ctrl+点击**多选分类和片段节点,多选后右键菜单提供「删除」和「批量导出分类」 - 右键分类节点:重命名 / 删除 / 新建子分类 / 导出分类 / 添加片段 - 右键分类树下片段节点:打开 / 复制 / 导出 / 删除 / 属性(与缩略图右键菜单一致) - 右键"全部":新建顶级分类 - 双击分类树下片段节点:在该分类的缩略图中打开片段 - 拖拽分类节点可调整排序;拖拽缩略图到分类节点可重新归类 - **缩略图列表**:网格视图展示搜索结果 / 分类筛选结果(通过可拖动的分隔条与分类树调节高度比例) - **单击**:选中片段(不打开),可 Ctrl+点击多选,拖拽调整排序 - **双击** 或 **Enter 键**:打开片段到编辑器(新标签页) - 右键点击(单选):弹出菜单(打开 / 复制 / 导出 / 删除 / 属性) - 右键点击(多选):弹出批量操作菜单(复制 / 删除 / 批量导出) - 拖拽到分类节点:移动片段到目标分类(支持多选拖拽) ### 中栏 - **多标签代码编辑器**:基于 `QTabWidget`,支持同时打开多个 TikZ 片段,标签页标题显示片段名称,未保存时显示 `*` 后缀 - 点击缩略图打开片段时自动创建新标签页,已打开的片段直接切换到对应标签页 - 标签页可关闭(× 按钮或 Ctrl+W),关闭前检查未保存更改(保存/放弃/取消) - 切换标签页时自动更新右侧的 PDF 预览、元数据表单和参数面板;每个标签页的元数据编辑(名称/简介/标签/宏包/库/模板)在标签页之间相互隔离,切换后元数据互不影响 - 退出程序时检查所有标签页的未保存更改,支持全部保存/全部放弃 - **代码编辑器**:基于 `QPlainTextEdit`,等宽字体(字号可调,默认 10pt),行号显示,当前行高亮,**TikZ/LaTeX 语法彩色高亮**,**选中词全文档高亮**,**智能代码补全**,**括号自动配对**(`{}`/`[]`/`()` 自动补全、选中文本包裹、闭合括号跳过覆盖、空括号对一键退格删除) - **编译日志**:精简显示 xelatex 输出,仅展示编译命令、警告、错误信息,红色 = 错误、橙色 = 警告 - 错误行号 `l.X` 自动换算为编辑器对应行号 - 双击日志行中的 `l.<行号>` 跳转编辑器对应行 ### 右栏 上部分为 **PDF 预览**,下部分为 **元数据编辑**(可拖拽分割条调整比例): - **PDF 预览**:Qt6 `QPdfView` 矢量渲染,支持工具栏缩放控制、鼠标滚轮缩放(以光标位置为中心)、左键拖拽平移。重新编译后保持当前缩放倍率和滚动位置,方便对比修改后的细节变化。 - **元数据表单**:名称、简介、标签、额外宏包、TikZ 库、模板选择 - **参数控件**:自动识别 `% @param:` 注释,动态生成输入框 - 右栏元数据区可在分割条拖到底时自动滚动 --- ## 核心功能说明 ### 片段管理 每个 TikZ 片段是一个独立目录,包含核心文件: ``` ~/.local/share/HiTikZ/TikzManager/ ├── snippets/ # 用户创建的片段 │ └── / │ ├── meta.json # 名称、简介、分类、标签、模板、宏包、TikZ 库、排序号、图片清单 │ ├── snippet.tex # \begin{tikzpicture}...\end{tikzpicture} 核心代码 │ ├── preview.png # 最后一次编译成功的缩略图 │ └── a.png ... # 片段图片(字母序号命名,见「图片管理」) ├── presets/ # 系统预置片段(首次启动从 resources/presets/ 拷贝) │ └── / ... ├── templates/ # LaTeX 模板(首次启动从 resources/templates/ 拷贝) │ └── *.tex ├── drafts/ # 自动保存的草稿(JSON 格式) │ └── *.json ├── category_order.json # 分类拖拽排序的持久化顺序 └── category_list.json # 独立持久化的分类列表(支持空分类存在) ``` **meta.json 格式示例**: ```json { "id": "10000000-0000-0000-0000-000000000001", "name": "勾股定理", "description": "勾股定理几何证明:直角三角形三边正方形面积关系", "category": "数学/几何", "tags": ["勾股定理", "几何", "三角形"], "templateId": "default_math", "packages": "", "tikzLibraries": "", "compileCommand": "", "sortOrder": 0.0, "images": ["a.png", "b.pdf"], "linkedPdf": "" } ``` ### 分类系统 - 支持层级分类,使用 `/` 分隔(如 `数学/几何`) - 分类独立持久化到 `category_list.json`,支持**空分类**存在(无片段的分类不会自动消失) - 新建子分类 / 顶级分类不再自动创建占位片段,可直接新建空分类容器 - 分类树节点下直接显示属于该分类的片段文件名,方便区分「直属片段」与「子分类内容」 - 分类树中单击片段名:下方缩略图栏仅显示该片段;双击片段名:打开到编辑器 - 分类树默认折叠,仅展开"全部"根节点和当前选中分类的路径,避免杂乱 - 拖拽缩略图到分类树节点即可重新归类(支持多选拖拽) - **分类拖拽排序**:直接拖拽分类节点可调整同级分类的排列顺序(含空分类),顺序持久化到 `category_order.json` - **分类树多选**:Ctrl+点击多选分类和片段节点,右键批量导出/删除所选内容 - **分类右键菜单**:重命名 / 删除分类 / 新建子分类 / 导出分类 / 添加片段 - **缩略图拖拽排序**:在分类内拖拽缩略图可自定义片段排列顺序,排序持久化到每个片段的 `meta.json`(`sortOrder` 字段为 double 浮点数,新建片段自动获得该分类最小值的 -1.0 排在首位) - 支持批量修改多个片段的分类 - 分类树节点显示片段数量(含子分类汇总数) - "全部"节点显示所有片段总数,"未分类"节点显示无分类的片段数 ### 模糊搜索 - 基于 Unicode 子序列匹配,使用 NFC 归一化和 case-folding 进行大小写不敏感匹配 - 双字(bigram)倒排索引:查询长度 ≥2 时通过索引快速筛选候选,再对候选做全匹配打分 - 打分规则:连续匹配字符得高分(`10 + consecutive * 5`),间隔匹配低分 - 名称匹配权重是简介的 2 倍 - 空搜索显示所有片段 ### 代码编辑器 - **语法高亮**(`TikzHighlighter`):基于 `QSyntaxHighlighter`,**14 条优先正则规则 + 跨行选项括号处理 + 用户定义动态规则** - 基础规则(按优先级): - 注释 `%` → 灰色斜体 - 字符串 `"..."` → 橙黄色 - 参数 `@@var@@` → 绿色斜体 - 环境 `\begin{...}` / `\end{...}` → 紫色加粗 - 命令 `\draw`、`\node` 等 → 蓝色加粗 - 数学模式 `$...$`、`\(...\)`、`\[...\]` → 绿色 - 坐标 `(x,y)` → 橙色 - 选项 `[...]` → 青色(通过块状态机跟踪,支持跨行选项列表) - 数字(含单位)→ 紫色 - 括号 `{` `}` → 红色 - PGF 路径 `/tikz/...`、`/pgf/...` 等 → 靛蓝色 - 键处理器 `/.style`、`/.code`、`/.default` 等 → 粉红色 - `\usetikzlibrary{...}` 库列表 → 棕色 - 用户定义规则(从 `TikzDocumentState` 实时读取): - 用户样式名 → 橙红加粗(如 `mystyle`、`test lines`) - 节点名 `(name)` → 深紫加粗 - 坐标名 → 金色 - foreach 变量 `\x` → 橄榄绿斜体 - 用户自定义命令 `\mycmd` → 青蓝加粗 - key=value 中的 key 名 → 深青加粗,与值分色(感知花括号深度,`{a=b}` 内部的 `=` 不会误标为键值分隔符;跨行选项通过 `InBracket` 块状态保持键值识别) - `TikzDocumentState` 通过 `CodeEditor` 注入,300 毫秒延迟后重新解析,用户定义名变化后自动重高亮 - **选中词高亮**:光标置于单词上或双击选中时,文档中所有相同单词以浅橙色背景高亮,辅助查看变量/命令的使用位置 - **自动缩进**:按 Enter 换行时自动继承上一行的前导空白,若行尾为 `{` 或以 `\begin` 开头则额外增加 4 空格缩进。当光标位于独占一行的 `{|}` 中间(前面仅有缩进)时按回车,`{` 之后新增两行:光标停在缩进一级的中间行,`}` 移至新增的第二行并与 `{` 缩进对齐,既保持美观又方便多行录入 - **块缩进 / 反缩进**:与主流编辑器一致,选中多行代码后按 `Tab` 键为每一行增加一级缩进(4 空格),按 `Shift+Tab` 为每一行减少一级缩进(最多移除一级前导空白);无选中时 `Shift+Tab` 反缩进当前行,用于手动对齐缩进 - **过长行自动换行**:由设置面板"行为设置 → 过长代码自动换行"控制(默认开启)。开启后过长的代码行在编辑器内软换行,无需横向滚动即可看到全部内容;行号栏按视觉行绘制——逻辑行的首行显示行号,软换行产生的续行显示 `↳` 标记,便于区分新行与续行 - **撤销/重做**:标准 Ctrl+Z / Ctrl+Shift+Z,工具栏有独立按钮 ### 代码补全 智能补全(`TikzCompleter`)基于**结构化词库**(`TikzKeywordDB`,2000+ 条带环境/命令/库元数据的结构化条目)和**文档状态追踪**(`TikzDocumentState`,范围栈/用户定义名/活动库/`\usepackage` 检测),实现三层精细过滤。补全上下文检测采用**跨行回溯**——从光标向前回溯到最近未闭合的 `[` 或 `{`(带回溯上限),因此换行书写的选项 / 参数也能正确识别上下文并补全: > **空括号不打扰**:当 `[]` 或 `()` 内尚无任何输入时(如刚由自动配对插入的空括号对),不会自动弹出一大堆补全项;此时可按 `Ctrl+Space` 手动激活补全弹窗。命令(`\`)、环境(`\begin{`/`\end{`)、库(`\usetikzlibrary{`)、锚点(`.`)等带明确前导符的上下文仍即时弹出。 **基础上下文**(13 种): | 上下文 | 触发条件 | 补全内容 | |--------|---------|---------| | 命令 | 输入 `\` 后接字母(`\` 前为 `{`/`(`/`[` 等非字母也可触发) | 按当前环境和激活库动态过滤的 TikZ/LaTeX/PGF/tkz-euclide 命令(仅提示合法的 `\` 命令,路径操作、选项、环境名等不会作为命令误提示) | | 环境 | `\begin{` 未闭合 | ~65 个 LaTeX/TikZ 环境,接受补全后自动插入 `\end{env}` 并关闭括号,光标留在 `\begin` 行尾 | | 结束环境 | `\end{` 未闭合 | ~65 个环境名,当前最内层未闭合环境自动排在首位 | | 选项 | `[...]` 内 | 环境/命令/库三级过滤的选项,含 473 个 CircuiTikZ 路径元件(`R`/`C`/`pR`/`vR`/`rmeterwa` 等,含前缀快捷方式及 full/empty/stroke 二极管变体、inline 逻辑端口) | | 锚点/键处理 | 字母或 `/` 后跟 `.` | 仅显示当前激活库可用的锚点(通用 16 个 + 库门控 40+ 个,含 circuitikz 的 `pin 1`–`pin 3` 等动态创建锚点)+ 16 个 PGF 键处理器;不使用或未激活的库锚点不出现 | | 值 | `=` 后 | **智能过滤 + 花括号感知**:`=` 查找忽略 `{}` 嵌套(`{a=b}` 不误触发),在 `{...}` 花括号内(如 `.style={>=|}`、`.style={font=\|}`)也能正确触发等值补全,按 key 名匹配——颜色键提示完整调色板及用户颜色,`pattern=` 仅提示图案,`decoration=` 提示全部 27 个装饰名,定位键(above/below/left/right)提示坐标/节点名,`label=`/`pin=` 提示方位(above / above left / …),`font=`/`node font=` 提示字体命令(`\itshape`/`\bfseries`/`\tiny`…\Huge,支持样式体内以 `\` 开头的值),`of=`(name intersections)提示用户命名路径。多库共享同名键(如 `column sep` 同属 matrix 与 tikz-cd)时取值提示并集 | | 路径操作词 | 路径体中 `\draw (0,0)` 之后的裸词(花括号深度 ≤ 0) | 精选的 ~24 个路径操作(`rectangle`/`circle`/`grid`/`arc`/`parabola`/`sin`/`cos`/`node` 等),只提示路径操作,不包含数学函数或形状名等不相关条目 | | 参数 | `@@` 未闭合 | 代码中声明的参数变量 | | TikZ 库 | `\usetikzlibrary{` 内 | ~88 个 TikZ 库名(从词库动态读取) | | 通用词 | 花括号内 `{...}` 中任意已知词 | 全部词表去重并集(~2200 词),适用于节点文本、数学表达式等场景 | | 坐标/节点名 | `(` 后 | 用户定义的坐标名、节点名(含路径操作形式的 `node[...] (name)` 如 `node [op amp] (OA)`、`\matrix (name)`、`name=` 语法含空格名如 `critical 1`、`name intersections={…,by={…}}` 中 `by=` 声明的交点名、circuitikz 的 `to[R, name=R1]` 及其 `R1start`/`R1end` 锚点坐标、pgfplots 的 `\begin{axis}[name=ax]`);同时提示 TikZ 坐标系写法如 `xyz cs:` 等(详见下方「坐标系补全」) | | 坐标系键 | `(<名> cs:` 之后 | 该坐标系的选项键——`xyz cylindrical cs:` 提示 `angle`/`radius`/`z`,`xyz spherical cs:` 提示 `angle`/`radius`/`latitude`/`longitude`,`canvas polar`/`xyz polar` 提示 `angle`/`radius`/`x radius`/`y radius` 等;库门控(`3d`/`calc`/`perspective`);键值 `=` 后保持静默不打扰 | | 用户命令 | `\` 后 | 用户通过 `\newcommand`/`\def` 定义的命令 | **环境过滤**:在 `\begin{circuitikz}...\end{circuitikz}` 内只显示电路相关选项,在 `\begin{axis}...\end{axis}` 内只显示 pgfplots 选项。环境自身会激活对应的补全库:`circuitikz` → circuitikz 补全、`tikzcd` → cd 补全、`feynman` → tikz-feynman 补全、axis 系列 → pgfplots 补全——无需在代码中写 `\usepackage` 或 `\usetikzlibrary`。 **命令过滤**:`\node[...]` 内额外显示形状/锚点/文本选项,`\draw[...]` 内额外显示线型/箭头/装饰选项。path 命令(draw/fill/to)也能提示 node 可用的选项(如形状)。`name path`/`name path global`/`name path local` 在 `\node` 与 `\draw`/`\path` 选项中均可用。 **含空格的补全值**:带空格的补全项(如定位键的 `of digit`、方位 `below left`)在选中上屏时按整段替换,不会在开头多出重复字符。 **to 路径**:`to path` 作为通用选项在 `\tikzset{}`/样式体(无命令上下文)中同样提示;其路径表达式内可补全坐标宏 `\tikztostart`/`\tikztotarget`/`\tikztonodes`。 **库过滤**:未加载 `decorations.pathmorphing` 库时不提示 `snake`/`coil`/`zigzag`;未加载 `angles` 库时不提示 `angle radius`/`angle eccentricity`。库门控覆盖全部主要 TikZ 库——chains(`start chain`/`on chain`/`join`)、spy(`spy using outlines`/`lens`/`magnification`)、through(`circle through`)、shadows(`shadow scale`/`shadow xshift`/`copy shadow`/`circular glow`)、shapes 系列(`rectangle split part fill`/`shape border uses incircle`/`callout absolute pointer`/`arrow box arrows`)、patterns.meta(`patterns/tile size`/`patterns/bounding box`)、trees(`sibling angle`)、mindmap(`root concept`/`concept connection`)、fit(`rotate fit`)、petri(`place`/`transition`/`token`/`tokens`/`colored tokens`/`children are tokens`/`token distance`)、automata(`state`/`accepting`/`accepting by arrow`/`initial`/`initial by diamond`/`state with output`)、backgrounds(`framed`/`gridded`/`show background grid`/`tight background`/`inner frame sep`/`outer frame xsep`)、positioning(`base left`/`base right`/`mid left`/`mid right`)、topaths(`loop`/`in control`/`out control`/`relative`/`min distance`/`max distance`,随 TikZ 常驻)、trees(`sibling angle`/`edge from parent fork down`/`grow via three points`/`clockwise from`)、er(`entity`/`relationship`/`attribute`/`key attribute`)、matrix(`above delimiter`/`below delimiter`/`nodes in empty cells`;`column sep`/`row sep` 提供距离与 `between origins`/`small`/`large` 等取值提示)、graphs(生长键 `grow right`/`grow down sep`/`branch left` 等、布局策略 `Cartesian placement`/`circular placement`/`no placement`/`chain shift`/`clockwise`/`phase`、节点存在策略 `use existing nodes`/`fresh nodes`、图模式 `simple`/`multi`/`quick`/`no edges`、节点与边键 `edges`/`math nodes`/`empty nodes`/`number nodes`/`typeset`/`as`/`name separator`/`trie`、边种类 `default edge kind`(值 `--`/`->`/`<-`/`<->`/`-!-`)/`new ->`/`new --` 等、锚点 `left anchor`/`right anchor`、源/目标边样式 `source edge style`/`target edge node`/`clear >`/`clear <`、`put node text on incoming/outgoing edges`、节点集合键 `V`/`W`/`n`/`m`/`name shore V`/`name shore W`/`declare`、命名图结构 `complete bipartite`/`matching`/`butterfly'` 及 `every graph`;`graphs.standard` 库门控子图 `subgraph I_n`/`I_nm`/`K_n`/`K_nm`/`C_n`/`P_n`/`Grid_n`/`G_np` 与其边概率键 `p`)、shadings(`upper left`/`upper right`/`lower left`/`lower right`)、mindmap(`root concept`/`concept connection`/`small mindmap`/`level 2 concept`/`circle connection bar switch color`)、3d(`canvas is xz plane at y`/`plane origin`/`plane x`)、quotes(`node quotes mean`/`edge quotes mean`/`quotes mean pin`)、decorations.text(`text effects`/`group letters`/`reverse text`/`fit text to path`)、calendar(`dates`/`day list right`/`week list`/`month label above centered`)、turtle(`fd`/`bk`/`lt`/`rt`)、lindenmayersystems(`axiom`/`rule set`/`l-system`)、fit(`rotate fit`)、perspective(`3d view`/`isometric view`)、spy(`spy scope`)、views(`meet`/`slice`)、intersections(`name path`/`name path global`/`name path local`)、rdf(`has type`/`is a bag`)、shapes.gates.logic(`and gate`/`use US style logic gates`/`logic gate symbol color`)、animations(`animate`)、decorations 全系列子选项键(`amplitude`/`segment length`/`pre length`/`post length`/`raise`/`mirror` 等 35+ 键)等。未加载 `circuitikz` 时不提示 CircuiTikZ 组件与锚点(`wiper`/`cathode`/`B`/`C`/`E` 等);circuitikz 激活后按 1.7.1 源码提供完整的双极子标注键(电流 `i` 全部 13 种变体 `i^>`/`i>_`/`i<^` 等、电压 9 种、流向 `f` 13 种、`l`/`l2`/`a`/`a2` 标签族及对齐键)、元件修饰键(`noinv input up`/`arrowmos`/`bodydiode`/`solderdot`/`num pins` 等 /tikz 级镜像键)、全部 25 个元件类的样式矩阵(`amplifiers/fill`、`RF/thickness`、`power supplies/scale` 等 `<类>/fill|scale|thickness` 键)、`\ctikzset`/`\ctikzflipx` 等用户命令,以及用户级配置键(`voltage shift`/`voltage dir`/`american`/`european` 系列等);未加载 `tkz-euclide` 时不提示 tkz-euclide 命令;未加载 `arrows.meta` 时不提示 `Stealth`/`Latex`/`Kite` 等 meta 箭头。`\usepackage{...}` 自动激活对应补全库:`circuitikz` / `tkz-euclide` / `tikz-cd`(→`cd`) / `chemfig` / `tikz-feynman` / `physics` / `siunitx` / `pgfplots` / `tikz-3dplot`(→`3d`)。编辑器内 `\usepackage`、片段「额外宏包」元数据字段、以及所选 LaTeX 模板中的 `\usepackage`/`\usetikzlibrary`(如 default_circuit 模板自带的 circuitikz)三者均可触发。 **数学物理宏包补全**:`\usepackage{physics}` 激活 physics 包约 136 个命令(`\vb`/`\va`/`\vu`/`\dv`/`\pdv`/`\grad`/`\div`/`\curl`/`\laplacian`/`\qty`/`\bra`/`\ket`/`\braket`/`\expval`/`\comm`/`\dd`/`\cross`/`\norm`/`\tr` 等);`\usepackage{siunitx}` 激活 siunitx 命令(`\SI`/`\si`/`\num`/`\ang`/`\qty`/`\unit`/`\numlist`/`\qtyrange`/`\sisetup` 等);`\usepackage{pgfplots}` 激活 pgfplots 键。这些命令仅在对应宏包被使用时才提示(编辑器 `\usepackage` 或片段「额外宏包」字段均可触发),不与纯 TikZ 补全混杂。 **专业绘图宏包补全**: - **CircuiTikZ**(`circuitikz`):473 个路径元件 + 141 个 node 形状 + 全局键(`voltage`/`current`/`voltage dir`/`logic ports`/各类 `scale`/`mirror`/`invert`/`l`/`v`/`i`/`a` 标注键等)+ 元件级样式键(`resistors/width`/`resistors/zigs`/`inductors/coils`/`capacitors/width` 等)+ 二极管族变体(`full diode`/`empty diode`/`stroke diode` 及 `D*`/`Do`/`D-` 等快捷方式)+ inline 逻辑端口(`inline not`/`inline buffer` 等)+ 四极子形状(`transformer`/`transformer core`/`gyrator` 等);锚点补全涵盖 `pin 1`–`pin 3`(flipflop/dipchip 的引脚触点)、`bpin 1`–`bpin 3`(引脚边框锚点)、Transformer 端口锚点(`A1`/`A2`/`B1`/`B2`/`AA1`/`AA2`/`BB1`/`BB2`/`inner dot A1` 等)。 - **tkz-euclide**(`tkz-euclide`):261 个 v5.10c 命令,涵盖定义点/线/圆/多边形/三角形、绘制、交点、角标注、变换等。v5 采用「先 `\tkzDef...` 定义、再 `\tkzDrawPolygon` 绘制」的写法,补全内容与 v5 API 保持一致。 - **tikz-cd**(`tikzcd` 环境):箭头方向快捷命令(`\ar`/`\rar`/`\lar`/`\uar`/`\dar`/`\urar`/`\ular`/`\drar`/`\dlar`)+ 箭头样式键(`rightarrow`/`hook`/`harpoon'`/`two heads`/`maps to`/`dashed`/`squiggly`/`equal` 等)+ 图表选项(`row sep`/`column sep`/`crossing over`/`phantom` 等)。 - **chemfig**(`chemfig`):约 40 个命令(`\chemfig`/`\definesubmol`/`\chemname`/`\chemabove`/`\schemestart`/`\charge`/`\polymerdelim` 等)+ `\setchemfig` 键(`atom sep`/`bond offset`/`double bond sep`/`angle increment`/`cram width`/`arrow offset` 等)。 - **tikz-feynman**(`tikz-feynman`):命令(`\feynmandiagram`/`\vertex`/`\diagram`/`\feynman`)+ 粒子/边样式(`fermion`/`anti fermion`/`photon`/`boson`/`scalar`/`ghost`/`gluon`/`majorana`/`momentum`/`half left` 等)。 > **词库来源**:补全词库中的命令、选项、形状、装饰、数学函数等条目,均以本地 TeX Live 源码为准逐条核对,力求与实际宏包 API 一致,避免收录不存在的命令或选项。参照的源码版本为 PGF/TikZ 3.1.10、pgfplots 1.18.1、CircuiTikZ 1.7.1、tkz-euclide 5.10c、tikz-cd、chemfig 1.66、tikz-feynman 1.1.0、physics、siunitx。 **用户定义补全**:实时解析代码中的自定义定义,自动纳入补全: - 样式:`\tikzset{name/.style={...}}`、`\tikzstyle{name}` → 选项上下文,含带连字符名(如 `sr-ff`)和空格名(如 `test lines`) - 坐标:`\coordinate (name) at ...`,以及路径操作写法 `\draw ... coordinate (name) ...`(如 `\draw (2,1) coordinate (test) circle [radius=2mm];`,可带 `[options]`)→ 坐标上下文与高亮 - 节点:`\node (name) ...`、`\pic (name) ...`、`\matrix (name) ...`、以及路径操作形式的 `node[...] (name)` 和 `pic[...] (name)`(如 `\draw (0,0) node [op amp] (OA) {...}`)、`\node[... name= ...]`(含 `name=` 选项语法)、circuitikz 元件的 `to[R, name=R1]`/`n=C1`(提取 `R1` 自身及其 `R1start`/`R1end` 锚点坐标)、pgfplots 的 `\begin{axis}[name=ax1]` → 坐标上下文 - foreach 变量:`\foreach \x in ...`、`\foreach \xyz / \xtext in ...`(支持空格分隔多变量及可选方括号参数如 `[count=\i]`)→ 命令上下文 - 命令:`\newcommand{\foo}`、`\def\foo`、`\edef\foo`、`\gdef\foo`、`\xdef\foo`、`\let\foo=\bar`(含省略 `=` 的写法)、`\pgfmathsetmacro{\foo}`、`\pgfmathsetlengthmacro{\foo}`、`\pgfmathtruncatemacro{\foo}`、`\NewDocumentCommand` 等 → 命令上下文 - 颜色:`\definecolor{name}`、`\colorlet{name}` → 值上下文(`color=`、`draw=`、`fill=` 等) - 命名路径:`name path=`、`name path global/local=`(含 `\node` 上的命名路径)→ `name intersections={of=…}` 的 `of=` 值上下文 - 交点名:`name intersections={…,by={[opt]A,B}}` 中 `by=` 声明的坐标名(自动剥离 `[options]` 前缀)→ 坐标上下文 - 定义删除后补全列表即时清空,不留残留项 **坐标系补全**:支持 TikZ 的坐标系写法 `(<名> cs:key=value,...)`,分两级补全: 1. 在 `(` 后提示坐标系名(自动附带 ` cs:` 标记),如 `xyz cs:`、`canvas polar cs:`、`xyz cylindrical cs:`、`xyz spherical cs:`; 2. 进入 `cs:` 之后按坐标系提示其选项键,键值 `=` 后保持静默(数值由用户输入)。 ```latex \draw (0,0,0) -- (xyz cylindrical cs:z=1,angle=90); \draw (0,0,0) -- (xyz spherical cs:radius=1,longitude=0,latitude=45); ``` 覆盖的坐标系与键(对照 PGF/TikZ 3.1.10 源码逐条核对): | 坐标系 | 选项键 | 库门控 | |--------|--------|--------| | `canvas` | `x`/`y` | 常驻 | | `canvas polar` | `angle`/`radius`/`x radius`/`y radius` | 常驻 | | `xyz` | `x`/`y`/`z` | 常驻 | | `xyz polar`(别名 `xy polar`) | `angle`/`radius`/`x radius`/`y radius` | 常驻 | | `node` | `name`/`anchor`/`angle` | 常驻 | | `barycentric` | (权重表达式) | 常驻 | | `intersection` | `first line`/`second line`/`first node`/`second node`/`solution`/`horizontal line through`/`vertical line through` | 常驻 | | `perpendicular` | `horizontal line through`/`vertical line through` | 常驻 | | `xyz cylindrical` | `angle`/`radius`/`z` | `3d` | | `xyz spherical` | `angle`/`radius`/`latitude`/`longitude` | `3d` | | `tangent` | `node`/`point` | `calc` | | `three point perspective`(别名 `tpp`) | `x`/`y`/`z` | `perspective` | > 未加载 `3d` 库时不提示 `xyz cylindrical`/`xyz spherical`;`calc`/`perspective` 同理。核心坐标系(canvas/xyz/polar/node/…)始终可用。 **tkz-euclide 5.10c 支持**(261 个命令):初始化/裁剪(`\tkzInit`/`\tkzClip`),定义点/线/圆/多边形/三角形及其特殊心(`\tkzDefPoint`/`\tkzDefLine`/`\tkzDefCircle`/`\tkzDefTriangle`/`\tkzDefTriangleCenter` 等),绘制点/线/段/多边形/圆/弧/扇形(`\tkzDrawPolygon`/`\tkzDrawCircle`/`\tkzDrawArc` 等),交点计算(`\tkzInterLL`/`\tkzInterLC`/`\tkzInterCC`),角标注(`\tkzMarkAngle`/`\tkzMarkRightAngle`/`\tkzLabelAngle`),标签、变换与全局样式设置。所有命令标记 `requiredLibs={"tkz-euclide"}`,仅在 `\usepackage{tkz-euclide}` 检测到后出现。 > **v5 vs v4**:tkz-euclide v5 采用「先 `\tkzDef...` 定义、再 `\tkzDrawPolygon` 绘制」的 API 风格,与 v4 的 `\tkzDrawTriangle`/`\tkzDrawSquare` 等直接绘图命令不同。补全词库以 v5.10c 为准。 ### LaTeX 编译与 PDF 预览 **编译流程**: 1. 加载选中模板,将额外宏包(`\usepackage`)和 TikZ 库(`\usetikzlibrary`)注入模板导言区 `\begin{document}` 前 2. 将 TikZ 核心代码注入模板的 `%%% TIKZ_CODE_HERE %%%` 位置 3. 写入临时 `.tex` 文件(位于 `/tmp/TikzManager//output.tex`) 4. 异步调用 `xelatex -interaction=nonstopmode -halt-on-error -shell-escape` 5. 编译成功 → PDF 加载到预览区 → 生成缩略图 PNG(150 DPI)→ 持久化到片段目录 6. 编译失败 → 日志面板精简显示错误和警告 → 双击跳转错误行(行号已自动映射到编辑器行号) **可自定义编译引擎**:每个片段可通过属性对话框(右键缩略图 → 属性)设置自定义编译命令,如 `lualatex -interaction=nonstopmode -shell-escape`。留空则使用默认 `xelatex -interaction=nonstopmode -halt-on-error -shell-escape`。支持 XeLaTeX / LuaLaTeX / PdfLaTeX 及自定义参数。该字段不显示在主界面右栏,属高级功能。 **编译日志**: - 顶部显示完整编译命令 - 成功:仅显示警告信息 + 编译成功标记 - 失败:显示错误块(含上下文)+ 警告信息 + 编译失败标记 - 自动过滤 `.sty`、`.cls`、`.aux` 等文件加载噪音行 - 错误行号 `l.X` 自动从完整文档行号换算为编辑器行号 ### 参数化系统 在 TikZ 代码中使用 `% @param:` 注释声明参数,`@@var@@` 作为占位符: ```latex % @param: angle=30 % @param: radius=2 \begin{tikzpicture} \draw (0,0) -- ({@@radius@@*cos(@@angle@@)}, {@@radius@@*sin(@@angle@@)}); \end{tikzpicture} ``` - **自动解析**:代码编辑时实时扫描 `% @param:` 行,动态生成 `变量名: [默认值]` 输入框 - **应用参数**:将 `@@var@@` 替换为输入框中的当前值后触发编译 - **批量预览**:生成所有预览时自动使用默认值替换参数 - **复制代码**:复制的代码为参数替换后的最终代码(注释行已移除) - **参数补全**:编辑器内输入 `@@` 可触发参数名补全(显示当前代码中声明的所有参数名) ### 自动保存与草稿恢复 - **定时保存**:每 3 分钟自动保存所有打开标签页的完整状态(代码 + 名称 + 简介 + 标签 + 额外宏包 + TikZ 库 + 模板 ID)为 JSON 草稿文件。仅对存在未保存更改(编辑器中以 `*` 标记)的标签页写入草稿,未修改的标签页不生成草稿,避免异常退出后的虚假恢复提示。每个未保存的草稿标签页使用独立编号文件名(如 `scratch_0.json`、`scratch_1.json`),防止多个草稿标签页相互覆盖 - **草稿恢复**:程序异常退出后下次启动时,自动弹出恢复对话框,列出所有未保存草稿的具体名称和简介,可勾选需要的草稿、全选、全部丢弃或稍后处理 - "恢复所选"后未勾选的草稿视为放弃并清理,"稍后处理"(或直接关闭对话框)保留草稿留待下次启动 - 以 `--hidden` 自启动时恢复对话框推迟到首次打开主窗口时再弹出,登录时不打扰 - 有对应片段的草稿恢复后加载到编辑器(不覆盖已保存版本) - 无对应片段的草稿自动创建为新片段后加载 - **关闭提示**:关闭标签页或退出程序时,如有未保存更改则弹出"保存 / 不保存 / 取消"对话框 - 临时片段(无关联保存片段)选择保存时弹出新建片段对话框 - 退出时选择"全部放弃"自动清理所有草稿文件 - 托盘"退出"菜单触发完整的关闭流程(包含未保存检查) - 窗口 X 按钮仅隐藏到托盘(不触发保存检查) ### 模板系统 三个极简 LaTeX 模板(额外宏包和 TikZ 库由每个片段自己声明): | 模板 | 用途 | 内置宏包 | |------|------|---------| | `default_math` | 数学图形 | `xcolor`, `amsmath`, `tikz` | | `default_physics` | 物理示意图 | `xcolor`, `tikz` | | `default_circuit` | 电路图 | `xcolor`, `tikz`, `circuitikz`, `preview`(active, tightpage) | 所有模板均使用 `standalone` 文档类(`border=1pt`),生成紧凑的独立 PDF。 模板文件位于 `~/.local/share/HiTikZ/TikzManager/templates/`,可通过设置面板的模板管理界面创建、编辑、删除。 ### 宏包与 TikZ 库 每个片段可声明自己需要的额外 LaTeX 宏包和 TikZ 库。右下角「额外宏包」「TikZ库」两栏均提供逗号感知的名称自动补全——仅匹配当前正在输入的最后一段(前序条目原样保留):额外宏包栏补全常用 LaTeX 宏包名(琥珀色弹窗),TikZ库栏补全 TikZ 库名(蓝色弹窗);两个补全弹窗使用各自的强调色背景、彩色圆点条目标记与等宽字体,与下方输入框及彼此均可一眼区分(明暗主题自适应)。TikZ库栏的改动会即时同步到编辑器的补全上下文(例如加入 `through` 后,代码里的 `circle through` 立即可补全),无需在代码中另写 `\usetikzlibrary`。 **额外宏包**(`packages` 字段): 用逗号分隔宏包名,可选参数用 `[options]` 前置,如: ``` tikz-3dplot,[european,nosiunitx]circuitikz,tikz-cd ``` 编译时自动展开为: ```latex \usepackage{tikz-3dplot} \usepackage[european,nosiunitx]{circuitikz} \usepackage{tikz-cd} ``` 解析器正确处理嵌套括号 `{}` 和 `[]`,如 `[option={val1,val2}]` 中的逗号不会错误分割。 **TikZ 库**(`tikzLibraries` 字段): 用逗号分隔库名,如: ``` calc,er,angles,patterns,decorations.pathmorphing,shadows.blur,pgfplots.fillbetween ``` 编译时自动展开为: ```latex \usetikzlibrary{calc,er,angles,patterns,decorations.pathmorphing,shadows.blur,pgfplots.fillbetween} ``` 两者均在编译时注入到模板 `\begin{document}` 之前。 ### 自定义命令处理 在 TikZ 代码编辑器中,与 TikZ 绘图层无关的 LaTeX 定义命令(`\newcommand`、`\tikzset` 等)约定写在 `\begin{tikzpicture}` 或 `\begin{circuitikz}` 环境**之外**(上方)。系统自动检测并抽取这些命令,在编译和复制文档时将其放入导言区(`\documentclass` 之后、`\begin{document}` 之前),确保编译正确。 **支持的定义命令清单**(共 40+ 类): | 命令 | 语法示例 | 说明 | |------|---------|------| | `\newcommand` / `\renewcommand` / `\providecommand` | `\newcommand{\foo}[2]{#1+#2}` 或 `\newcommand\foo[2]{#1+#2}` | 旧格式,支持 `*` 变体 | | `\NewDocumentCommand` / `\RenewDocumentCommand` / `\ProvideDocumentCommand` / `\DeclareDocumentCommand` | `\NewDocumentCommand{\foo}{ O{red} m }{\draw[#1] #2;}` | xparse 新格式 | | `\NewExpandableDocumentCommand` | `\NewExpandableDocumentCommand{\foo}{ m }{#1}` | 可展开变体 | | `\NewCommandCopy` | `\NewCommandCopy{\new}{\old}` | 命令复制 | | `\DeclareMathOperator` | `\DeclareMathOperator{\argmax}{argmax}` | 数学算子声明 | | `\DeclareRobustCommand` | `\DeclareRobustCommand{\foo}[1]{#1}` | 鲁棒命令 | | `\tikzset` | `\tikzset{style/.style={draw=red}}` | TikZ 样式和 pic 定义 | | `\tikzstyle` | `\tikzstyle{name}=[options]` 或 `\tikzstyle{name}+=[...]` | 旧版 TikZ 样式(兼容) | | `\ctikzset` | `\ctikzset{bipoles/length=1cm}` | CircuitikZ 全局设置 | | `\pgfkeys` | `\pgfkeys{/tikz/line width=1pt}` | PGF 键值设置 | | `\pgfplotsset` | `\pgfplotsset{compat=1.18}` | pgfplots 兼容性设置 | | `\definecolor` | `\definecolor{myblue}{RGB}{20,20,100}` | 颜色定义 | | `\colorlet` | `\colorlet{myshadow}{blue!50!white}` | 颜色别名 | | `\contourlength` | `\contourlength{1.4pt}` | 轮廓文本线宽(contour 包) | | `\pgfmathsetmacro` / `\pgfmathsetlength` | `\pgfmathsetmacro{\n}{round(10/3)}` | PGF 数学宏/长度定义 | | `\pgfmathdeclarerandomlist` | `\pgfmathdeclarerandomlist{lst}{{a}{b}}` | PGF 随机列表声明 | | `\pgfmathdeclarefunction` | `\pgfmathdeclarefunction{f}{1}{#1*#1}` | PGF 自定义数学函数 | | `\def` / `\edef` / `\gdef` / `\xdef` | `\def\mymacro#1{#1}` / `\edef\bar{...}` / `\gdef\baz#1{...}` | TeX 原语定义/展开/全局定义 | | `\let` | `\let\newcmd=\oldcmd` 或 `\let\newcmd\oldcmd`(`=` 可选) | TeX 原语别名 | | `\newif` / `\newboolean` / `\setboolean` | `\newboolean{show}` `\setboolean{show}{true}` | 条件开关(ifthen) | | `\newlength` / `\newcounter` / `\newsavebox` | `\newlength{\mylen}` | 寄存器分配 | | `\setlength` | `\setlength{\parindent}{0pt}` | 长度设置 | | `\setcounter` | `\setcounter{page}{1}` | 计数器设置 | | `\sansmath` | `\sansmath` | 无衬线数学字体 | | `\pgfdeclarelayer` / `\pgfsetlayers` | `\pgfdeclarelayer{bg}` `\pgfsetlayers{bg,main}` | PGF 图层管理 | | `\pgfdeclareradialshading` / `\pgfdeclareverticalshading` | `\pgfdeclareradialshading[tikz@ball]{ring}{...}` | PGF 自定义渐变着色 | | `\tikzoption` | `\tikzoption{myoption}{myvalue}` | 旧版 TikZ 选项定义(兼容) | | `\pgfdeclaredecoration` | `\pgfdeclaredecoration{name}{initial}{...}` | PGF 自定义装饰 | | `\usepgfplotslibrary` | `\usepgfplotslibrary{fillbetween}` | pgfplots 库 | | `\tdplotsetmaincoords` | `\tdplotsetmaincoords{70}{110}` | tikz-3dplot 视角设置 | | `\tikzmath` | `\tikzmath{ \x = 10; }` | TikZ 数学运算 | | `\PreviewEnvironment` | `\PreviewEnvironment{tikzpicture}` | preview 包环境声明 | | `\makeatletter` / `\makeatother` | `\makeatletter` … `\makeatother` | @ 字符类别切换 | **抽取规则**: - 仅提取 `\begin{tikzpicture}` / `\begin{circuitikz}` **之前**的定义命令 - 环境内部的命令(如图内 `\tikzset`)原样保留不提取 - 多行定义、嵌套花括号、混合格式(新旧混用、花括号/无花括号混用)均正确解析 - 参数与正文之间的空白/换行被容忍,如 `\newcommand{\foo}[2]`(换行)`{...}` 也能完整抽取 - 带分隔符参数文本的 `\def` 正确解析,如 `\def\foo[size=#1](#2,#3){...}`(参数文本含 `[]`/`()`/`#n`) - 遇到不完整/无法解析的定义(如 `\newcommand{\foo}` 无 `{body}`)时安全跳过,不中断后续命令的提取 - 编译时:先注入宏包和 TikZ 库,再注入自定义命令,确保依赖顺序正确 - 清理时保留换行分隔符,防止 LaTeX 注释行与后续命令合并 - 命令上方紧邻的注释行(含多行注释块)与命令行尾的 `%` 注释随命令一同抽取,保持注释与代码的位置关系;图片内部的注释原样保留 - 复制文档/导出 .tex 时:抽取 → 注入完整文档导言区 ### 完整文档复制 工具栏"复制文档"按钮将当前片段的模板头部 + 额外宏包 + TikZ 库 + 自定义命令 + 参数替换后的 TikZ 代码组合成**完整可编译的 LaTeX 文档**复制到剪贴板。导言区中的自定义命令连同其上方注释行与行尾注释一并迁移,图片内部的注释原样保留,注释与代码的位置关系保持不变。 生成的完整文档以**元数据注释块**开头,携带片段的名称、简介、标签(见[文档元数据注释](#文档元数据注释)),例如: ```latex %% name: 空间几何作图 %% description: 勾股定理的几何证明 %% tags: 几何, 勾股定理 \documentclass[tikz, border=5pt]{standalone} ... ``` ### 文档元数据注释 完整 LaTeX 文档(复制文档、复制文件、导出为 Tex 文档)在文档最开头以注释形式依次携带片段的**名称(name)、简介(description)、标签(tags)**三种信息——人可直接阅读,程序可正逆解析: ``` %% name: 空间几何作图 %% description: 简介内容(多行时每个换行拆为一条 description 注释行) %% tags: 几何, 空间 ``` - **正向(生成)**:导出或生成完整可编译 LaTeX 文件时,某个字段为空则**不输出**对应注释行,三个字段全为空则不输出元数据块 - **逆向(导入)**:导入 .tex 文件或从剪贴板导入时,解析文档开头的元数据注释块并写入片段元数据;解析后这些注释行从导入内容中移除(文档正文里的同形注释不受影响,仅文档开头的注释块参与解析) - **名称回退规则**:`%% name:` 未解析出来时,文件导入沿用文件名作为片段名;剪贴板导入(或无法取名时)默认名称「导入文件」;简介与标签未解析出来时默认为空 - 单 `%` 与 `%%` 注释均可解析,同一字段出现多次时以第一条为准(多行简介除外,按行拼接) - **重新导入自产文档**:用「复制文档 / 复制文件 / 导出为 Tex 文档」生成的文件再导入时,名称、简介、标签原样恢复 ### 多选与批量操作 - **Ctrl+点击**缩略图可多选(不触发编辑器加载) - **缩略图多选右键菜单**: - **复制**:复制所有选中片段(保留元数据、标签等) - **删除**:确认后批量删除 - **批量导出**:打包为单个 `.tar.gz` - **分类树 Ctrl+点击多选**:可同时选中多个分类节点和片段节点 - **删除**:删除选中分类及其全部内容 + 删除直接选中的片段 - **批量导出分类**:收集所有选中分类(含子分类)的片段 + 直接选中的片段,打包为 `.tar.gz` 导出 - 单击未选中节点(左键或右键)会清除多选,恢复单项操作菜单 - **分类树右键菜单**:重命名 / 删除 / 新建子分类 / 导出分类 / 添加片段 ### 片段复制 - **工具栏"复制片段"**:复制当前打开片段的所有内容(代码、元数据、标签、图片文件等) - **缩略图右键 → 复制**:在后台复制选中的片段(不切换到编辑器,图片一并复制) - **分类树右键片段节点 → 复制**:同上 ### 剪贴板操作 | 操作 | 说明 | |------|------| | 复制代码 | 复制参数替换后的 TikZ 核心代码 | | 复制文档 | 复制含模板头部的完整 LaTeX 文档(开头携带名称/简介/标签元数据注释,见[文档元数据注释](#文档元数据注释)) | | 复制 PNG | 从 PDF 转换 300 DPI PNG 后复制到剪贴板(与复制SVG互斥,防止并发冲突) | | 复制 SVG | 从 PDF 转换 SVG 后复制(附带 `image/svg+xml` MIME 类型),转换工具可在设置中切换(与复制PNG互斥,防止并发冲突) | | 复制链接 | 将当前片段的预览 PDF 以序号文件名链接到图片目录(默认 `~/PicTikZ`),复制 `\includegraphics` 引用命令到剪贴板(见[复制链接](#复制链接)) | | 复制文件 | 生成完整可编译 .tex 文档(开头携带名称/简介/标签元数据注释)并复制编译 PDF 与片段图片,以 `000.tex` / `000.pdf` / `a.png`… 文件名通过剪贴板 `text/uri-list` 提供,在 Dolphin 中 Ctrl+V 即可粘贴 | ### 导入与导出 **导出**:使用异步进程(非阻塞)调用 `tar` 打包,支持多种粒度和格式: - **导出当前 / 导出全部**:打包为 `.tar.gz` 归档 - **批量导出所选**:多选后右键菜单批量打包 - **导出为 Tex 文档**:生成含模板头部的完整可编译 LaTeX 文档(开头携带名称/简介/标签元数据注释,见[文档元数据注释](#文档元数据注释)) - **导出为 PDF 文档**:复制预览 PDF 到指定路径 - **导出为 PNG 图片**:通过 pdftocairo 将预览 PDF 转换为 PNG(DPI 遵循设置面板配置) - **导出为 SVG 图片**:通过 pdftocairo 或 Inkscape(可在设置面板中切换)将预览 PDF 转换为 SVG 矢量图 **导入**: - **导入存档**:选择 `.tar.gz` 或 `.zip` 文件 → 异步解压并为每个片段分配新 UUID → 先读取 `snippet.tex` 内容再调用保存逻辑 → 刷新列表。导入时自动清除 `isPreset` 标记,若缺失 `meta.json` 则自动创建片段 - **导入 .tex 文件**:选择单个 `.tex` 文件 → 自动提取 TikZ 代码(`\begin{document}...\end{document}` 之间 → `\begin{tikzpicture}...\end{tikzpicture}` → 全文回退三段式解析),同时从导言区解析: - `\usepackage{}`(含可选参数 `[...]`)→ 填入宏包字段 - `\usetikzlibrary{}` → 填入 TikZ 库字段 - 自定义命令(`\newcommand`、`\tikzset` 等)→ 提取后放置在 TikZ 代码上方 - 文档开头的元数据注释块(`%% name:` / `%% description:` / `%% tags:`)→ 填入名称、简介、标签(见[文档元数据注释](#文档元数据注释));未解析出名称时沿用文件名 - 根据宏包自动选择模板(含 circuitikz → `default_circuit`,否则 `default_math`) - **从剪贴板导入**:直接读取剪贴板中的完整 `.tex` 源代码,执行与 `.tex` 导入相同的解析流程(宏包、库、自定义命令、元数据注释、模板自动检测),无需先创建文件;未解析出名称时默认片段名「导入文件」,简介与标签默认为空 ### 图片管理 TikZ 片段可以附带图片文件(位图如 PNG/JPG/TIF,以及 PDF),用于对现成图片进行标注、叠加绘制等场景。在代码中通过 `\includegraphics{a.png}` 直接引用(PGF 内核已自动加载 `graphicx`,无需声明额外宏包): ```latex \begin{tikzpicture} \node[anchor=south west,inner sep=0] at (0,0) {\includegraphics[width=6cm]{a.png}}; \draw[red,thick,->] (1.2,0.8) -- (2.4,1.6) node[above] {标注}; \end{tikzpicture} ``` **入口**:右键缩略图(或分类树下片段节点)→ 属性,对话框中的「图片管理」区域提供: - **导入图片...**:文件对话框多选导入(支持 `png/jpg/jpeg/tif/tiff/bmp/gif/webp/pdf`),一次可导入多张、多种格式 - **粘贴图片 (Ctrl+V)**:将剪贴板中的图像(如截图工具)或从文件管理器复制(Ctrl+C)的图片文件直接导入;对话框内无文本输入框焦点时直接按 `Ctrl+V` 即可 - **查看**:调用系统默认图片查看器打开所选图片(双击列表项亦可) - **替换...**:用新文件替换所选图片(保留字母序号,扩展名随新文件更新) - **删除**:移除所选图片(代码中的引用需同步清理) - **复制文件名**:将文件名(如 `a.png`)复制到剪贴板,便于粘贴进 `\includegraphics{...}` 「查看 / 替换... / 删除 / 复制文件名」在刚打开对话框时呈灰色禁用状态,选中列表中的某张图片后才可点击。 **存储与命名**:图片存放在片段自身目录内(与 `snippet.tex`、`meta.json` 同级),统一按字母序号命名——`a.png`、`b.png`、`c.pdf`、`d.tif`…… 超过 `z` 后为 `aa`、`ab`…… 命名自动跳过已占用序号。文件名记录在 `meta.json` 的 `images` 字段(JSON 数组)。读取旧版没有该字段的 `meta.json` 时自动视为无图片,不受影响。 **全流程联动**: - **编译**:编译预览 / 应用参数 / 批量生成预览时,图片自动复制到编译临时目录,`\includegraphics` 无需写路径即可找到 - **导入导出**:`.tar.gz` 存档导入导出自动携带图片文件与 `images` 字段 - **复制片段**:复制/批量复制片段时图片文件一并复制,新片段可直接编译 - **复制文件**:工具栏「复制文件」除 `000.tex`/`000.pdf` 外同时附带片段图片,粘贴到任意目录后完整可编译 - **导出为 Tex 文档**:导出 `.tex` 时将图片复制到同一目录,导出文档独立可编译 - **删除片段**:连同其图片目录一并删除 ### 复制链接 在大量制作某个课件(或论文、习题集)的插图时,把每张插图逐一复制、粘贴、重命名进课件 TeX 项目是纯粹的重复劳动。由于生成 TikZ 图片的程序就在本地,「复制链接」直接用链接取代了这些步骤——图片编辑与文档写作彻底分离: **工作流**: 1. 选中片段并编译预览后,点击工具栏「复制链接」(位于「复制SVG」与「复制文件」之间) 2. 程序在链接图片目录(默认 `~/PicTikZ`,可在设置面板「路径设置 → 链接图片目录」中修改)内为当前片段的预览 PDF 创建**符号链接**,按序号命名:`0001.pdf`、`0002.pdf`、`0003.pdf`…… 3. 同时向剪贴板写入 LaTeX 引用命令,如 `\includegraphics{~/PicTikZ/0002.pdf}`,直接粘贴进课件文档即可使用 4. 之后修改该 TikZ 片段并重新编译,课件里的图片**自动更新**——只需重新编译课件文档,无需任何复制粘贴 **命名与重复点击**: - 链接文件名记录在片段 `meta.json` 的 `linkedPdf` 字段;再次点击「复制链接」时,若链接文件存在则跳过创建,直接复制引用命令 - 若记录的文件名存在但链接文件已丢失(或失效),点击时自动按原文件名重建 - 新片段分配序号时自动**填补空缺**:目录中存在 `0001.pdf`、`0003.pdf`、`0004.pdf` 时,下一个新链接是 `0002.pdf` 而非 `0005.pdf`(仅 `<数字>.pdf` 文件占用序号,失效链接同样保留序号) - 引用命令中的目录与设置保持一致:默认是 `~/PicTikZ`,修改链接图片目录后,新复制到剪贴板的命令自动使用新目录 **属性对话框**:右键缩略图(或分类树下片段节点)→ 属性,「超链接图片」区域显示该片段是否已创建超链接及对应文件名(含完整路径;链接文件失效或缺失时以警示色提示),并提供「删除超链接文件」按钮——删除链接目录中的文件并清除 `linkedPdf` 字段。未创建超链接的片段该按钮呈灰色禁用状态。 **其他联动**: - 链接指向片段自身目录中的 `preview.pdf`,每次编译成功都会覆盖该文件,因此链接始终指向最新图片 - 复制片段不会复制链接(每个副本按需独立分配序号) - 导入存档时自动清除 `linkedPdf` 字段(链接目录不随存档打包,避免与目标机器上其他片段的链接冲突);旧版无该字段的 `meta.json` 不受影响 - 未保存的新片段需先保存后才能使用「复制链接」(文件名需要写入片段元数据) --- ### 打包链接图片到项目(命令行 pack) 「复制链接」让插图与写作分离,但把 LaTeX 文档项目分享给别人时,链接目录(`~/PicTikZ`)并不随项目走。`hitikz pack` 命令行工具**读取 `.tex` 文档中的引用**,把文档**用到的**链接图片复制进项目目录(普通文件而非符号链接),并把相应 `\includegraphics` 引用改为新路径,最终文档项目可独立编译、可直接分享。链接目录通常被多个项目共用(课件的图、试卷的图都在一起),因此**只有被处理的文档引用到的图片才会被复制**,未引用的图片保持不动: ```bash hitikz pack [选项] <目标目录> ``` | 参数 | 必选 | 说明 | |------|------|------| | `` | 是 | 需要处理的 TeX 文件名或目录名。文件名支持 Linux 通配符(`*`、`?`,如 `slides/*.tex`);目录名时处理该目录下的所有 `.tex` 文件 | | `<目标目录>` | 是 | 保存 PDF 图片(及可选源码)的目录;重写后的引用使用**调用时填写的目录字符串原样**(相对目录如 `pics` 即生成 `pics/023.pdf` 形式引用) | | `--link-dir <目录>` | 否 | 复制链接的图片所在目录;缺省读取程序设置(设置面板「路径设置 → 链接图片目录」,默认 `~/PicTikZ`) | | `--name-format <格式>` | 否 | 新文件名格式:`01`(01、02、03…)、`001`(001、002…)、`0001`(0001、0002…),默认 `001` | | `--overwrite` | 否 | 覆盖目标目录中的同名文件。默认不覆盖:**跳过已有编号并顺延**,与原有文件共存 | | `--copy-sources` | 否 | 同时复制原 TikZ 片段的完整文件(行为相当于工具栏「复制文件」后粘贴改名)。默认只复制 PDF 图片 | | `--help` | 否 | 显示帮助(`hitikz --help` 也会列出 pack 子命令提示) | **示例**: ```bash # 把课件文档引用的 ~/PicTikZ 图片复制进项目的 pics 目录,引用改为 pics/001.pdf … hitikz pack course.tex pics # 处理目录下所有 .tex(或使用通配符),自定义链接目录与命名格式 hitikz pack --link-dir ~/PicTikZ --name-format 01 slides/ slides/pics ``` **按需复制规则**: - 先扫描全部待处理 `.tex` 文档中的 `\includegraphics`,只有指向链接目录(`~` 展开、相对路径、符号链接目录等写法均可识别)的引用才参与复制;同一目录下未被引用的链接图片完全不动,继续供其它文档项目使用 - 引用可省略 `.pdf` 扩展名(`\includegraphics{~/PicTikZ/0001}` 视为 `0001.pdf`) - 引用的图片在链接目录中已不存在(或失效)时打印 `引用的链接图片不存在: 0001.pdf`,该引用保持不变、其余图片照常处理,最终以退出码 `1` 结束 - 文档没有引用任何链接图片时打印提示并以 `0` 退出(什么都不做) - 编号只按**被复制**的图片分配:链接目录有 `0001/0002/0003.pdf` 而文档只引用 `0001.pdf` 与 `0003.pdf` 时,新名字为 `001.pdf`、`002.pdf`(`0002.pdf` 不参与、不占号) **编号与共存规则**(与「复制链接」的空缺填补一致): - 不覆盖时按数字从小到大寻找空缺:目标目录已有 `01.pdf`、`03.pdf`,新图片从 `02.pdf` 开始,接着是 `04.pdf`;终端会打印 `跳过已存在的文件: 01.pdf`、`跳过已存在的文件: 03.pdf`,原有文件完整保留 - 覆盖时从 `01` 起顺序编号并替换同名文件,终端以 `覆盖已存在的文件: 01.pdf` 着重提示,被覆盖文件将丢失 - 一个编号对应一组文件:`014.pdf`(图片)、`014.tex`(完整源码)、`014_a.png`、`014_b.png`…(关联图片,字母序与片段图片原名一致,如 `a.png` → `014_a.png`)。不覆盖时整组视为已占用,避免与上一次运行的残留文件冲突 **引用改写规则**(改动极小、只动图片路径): - 仅改写指向链接目录的 `\includegraphics{...}`(`~` 展开、相对路径、符号链接目录等写法均可识别),其它任何内容原样保留 - 可选参数(如 `\includegraphics[width=0.5\textwidth]{...}`)原样保留,仅替换花括号内的路径 - 一幅图片在一处文档中被引用多次会全部改写;图片被多个 `.tex` 文件(通配符/目录)引用时同样全部改写 - 注释掉的 `\includegraphics` 不处理 **源码复制(`--copy-sources`)**:链接 PDF 对应编号为 `014.pdf` 时,同时生成 `014.tex`(完整可编译文档,开头带名称/简介/标签元数据注释)与该片段关联图片(`014_a.png` 等);`014.tex` 内部的图片引用同步改为新名字,粘贴到目标目录即可独立编译。程序通过链接文件解析所属片段,失效链接或找不到片段的链接只复制 PDF 并给出警告。 **退出码**:`0` 成功;`1` 运行时错误(如链接目录不存在、引用的图片缺失、个别文件复制失败——成功部分照常完成,但引用未改写);`2` 参数错误(同时打印帮助)。命令不启动图形界面,可通过 SSH 使用。 --- ## 键盘快捷键 以下 8 项操作均可在**设置面板 → 快捷键设置**中自定义键序列,清空则禁用该快捷键。编辑器内置快捷键(`Tab`/`Shift+Tab` 块缩进、`Ctrl+Space` 补全、`Ctrl+Z` 撤销、`Ctrl+Shift+Z` 重做)为固定键位。 | 功能 | 默认快捷键 | |------|----------| | 全局快捷键:显示/隐藏窗口 | 无(可在设置中自定义) | | 撤销 | `Ctrl+Z` | | 重做 | `Ctrl+Shift+Z` | | 手动触发代码补全 | `Ctrl+Space` | | 块缩进 / 反缩进(多行选中) | `Tab` / `Shift+Tab` | | 复制 TikZ 代码 | 无(可在设置中自定义) | | 复制 PNG | 无(可在设置中自定义) | | 复制 SVG | 无(可在设置中自定义) | | 编译预览 | `F6` | | 应用参数 | 无(可在设置中自定义) | | 保存 | `Ctrl+S` | | 关闭标签页 | `Ctrl+W` | --- ## 预置片段清单 程序内置 120 个高质量 TikZ 教学示例,均从 [tikz.net](https://tikz.net) 和 [TeXample.net](https://texample.net) 精选并经过 XeLaTeX 编译验证,所有标题、描述、标签已本地化为中文。 ### 分类统计 | 学科 | 数量 | 主要分类 | |------|------|---------| | 数学 | 23 | 几何、函数、微积分、统计、分析、拓扑、艺术 | | 物理 | 89 | 力学、电磁学、光学、热力学、流体力学、相对论、量子、粒子物理 | | 电路 | 5 | 交流电路、RC电路、变压器 | | 化学 | 3 | 元素周期表、有机分子、物理化学 | ### 数学类(23 个) **数学/几何**(7 个):垂线作图、简单曲线、光滑曲线的控制点、自定义光滑曲线端点、球体体积、角度与标注、角平分线 **数学/函数**(3 个):函数图像、极坐标、函数图像 - 坐标轴环境:反正弦/反余弦/反正切 **数学/微积分**(5 个):柱坐标体积微分、直角坐标体积微分、球坐标表面积微分、函数平均值 - 线性函数、函数平均值 - 正弦函数 **数学/统计**(4 个):正态分布、线性回归、高斯分布 - 68-95-99法则、高斯分布 - CLs方法 p值(大重叠) **数学/分析**(2 个):复数平面 - 复振子三维、复数平面 - 复数旋转 **数学/拓扑**(1 个):平面到环面 **数学/艺术**(1 个):彭罗斯三角 - 变体2 ### 物理类(89 个) **物理/力学**(33 个):弹簧、滑轮系统、加速度、能量与功、抛体运动、弹簧 - 垂直弹簧静止伸长、弹簧 - 水平双弹簧、简谐振子 - 圆上相位、简谐振子 - 余弦阻尼、简谐振子 - 余弦过阻尼、滑轮系统 - 桌面滑轮弹簧、滑轮系统 - 桌面双滑轮、滑轮系统 - 天花板定滑轮、滑轮系统 - 天花板滑轮人力、摩擦力 - 水平地面举升、摩擦力 - 倾斜地面、物体稳定性 - 不稳定性(含中性平衡)、滑块稳定性 - 扭矩、扭矩 - 扭矩角度、转动惯量 - 圆环(二维)、转动惯量 - 圆环(三维)、转动惯量 - 圆环三维(平行轴定理)、转动惯量 - 空心圆柱、转动惯量 - 圆盘滑轮质量块、转动惯量(简化) - 细杆轴在一端、转动惯量(简化) - 圆盘、转动惯量(简化) - 空心圆盘、转动惯量(简化) - 圆环、转动惯量(简化) - 实心圆柱、转动惯量(简化) - 空心圆柱、转动惯量(简化) - 球体、振子近似 - 谐振子能量、摆与滑块 - 摆的解 **物理/电磁学**(32 个):电磁波、霍尔效应、毕奥-萨伐尔定律、电流、磁力、球体电场、电场线1、电场线2、镜像电荷(平面)、镜像电荷(球体)、电磁波谱、变压器、变压器绕组、电磁波 - 彩色电磁波、霍尔效应 - 水平磁场俯视图、电流 - 传导模型、楞次定律 - 电流环磁场(NS退出)、磁场 - 水平磁场速度沿场方向、磁力 - 铁钉吸引磁铁SN、磁矩 - 磁矩翻转、电场 - 垂直电场、电场 - 路径积分、球体电场 - 带电实心球体三维、球体电场 - 带空腔导体、平面电场 - 圆形薄板积分、平面电场 - 含电场线、平面电场 - 含高斯面、电场线1 - 正点电荷等势面、电场线1 - 负点电荷等势面、体电场 - 体电荷、镜像电荷(平面) - 电场线、镜像电荷(球体) - 电场线 **物理/光学**(10 个):光学折射、透镜、棱镜、棱镜2、光学棱镜、透镜像差、相位延迟片、光学折射 - 布儒斯特偏振角、光学偏振 - 偏振 90°与0°、光学偏振 - 偏振 90°/45°/0° **物理/热力学**(6 个):黑体辐射颜色、理想气体、热力学P-V图 - 等温线、热力学P-V图 - 卡诺循环、理想气体 - 盒中气体(有隔板)、理想气体 - 盒中气体(无隔板) **物理/流体力学**(5 个):伯努利原理、伯努利原理 - 伯努利方程、伯努利原理 - 文丘里效应、气压计(流体力学) - 开管压力计、气压计(流体力学) - 压力计 **物理/相对论**(1 个):彭罗斯图 **物理/量子**(1 个):布洛赫球 **物理/粒子物理**(1 个):CMS三维坐标轴 - CMS坐标系(含LHC) ### 电路类(5 个) 变压器电路、电容电路 - 电容并联、RC电路 - 开关闭合、RC+EMF电路 - 开关断开、交流电路波形 - LCR串联 ### 化学类(3 个) 元素周期表、有机分子结构、分子振动 --- ## 数据存储 所有用户数据存储在 `~/.local/share/HiTikZ/TikzManager/`: ``` ~/.local/share/HiTikZ/TikzManager/ ├── snippets/ # 用户创建/导入的片段 │ └── / │ ├── meta.json │ ├── snippet.tex │ └── preview.png ├── presets/ # 系统预置(首次运行拷贝自 resources/presets/) │ └── / ... ├── templates/ # 用户自定义模板(首次运行拷贝自 resources/templates/) │ └── *.tex ├── drafts/ # 自动保存的草稿 │ └── *.json ├── category_order.json # 分类拖拽排序的持久化顺序 └── category_list.json # 独立持久化的分类列表(支持空分类存在) ``` 程序配置通过 `QSettings` 存储,包括: - `xelatex/path`, `pdftocairo/path`, `inkscape/path`, `tools/pdfViewer`, `svg/tool`, `paths/texinputs`, `png/dpi` - `link/dir` — 「复制链接」的链接图片目录(默认 `~/PicTikZ`) - `editor/fontSize` — 代码字体大小 - `ui/fontSize` — 界面字体大小 - `behavior/autoCompileOnSave` — 保存后自动编译(默认开启) - `behavior/threadCount` — 批量预览并行线程数(默认 6) - `behavior/wrapLongLines` — 过长代码自动换行(默认开启) - `behavior/bracketHighlight` — 括号配对高亮(默认关闭,需用户手动开启) - `shortcuts/copyCode`, `shortcuts/copyPng`, `shortcuts/copySvg` - `shortcuts/compile`, `shortcuts/applyParams`, `shortcuts/save`, `shortcuts/closeTab` - `shortcuts/globalHotkey` — 全局快捷键 --- ## 设置面板 工具栏"设置"按钮打开设置对话框,包含以下区域: **路径设置**: - xelatex / pdftocairo / inkscape 命令(默认从 `$PATH` 查找,可填绝对路径) - **外部 PDF 查看器**:配置查看器命令及其启动参数(如 `okular --unique`、`evince`、`xdg-open`),工具栏「外部PDF」按钮使用此配置打开当前编译 PDF - SVG 转换工具选择:pdftocairo 或 inkscape - **命令搜索路径**:额外的可执行文件目录(多个用冒号分隔)。这些目录会被加入所有子进程的 `PATH`(同时也加入 `TEXINPUTS`),用于查找 `xelatex`/`pdftocairo`/`inkscape` 等命令。**从桌面图标启动、系统 `PATH` 不含 TeX Live 时尤其有用**——例如 TeX Live 用户可填入 `/usr/local/texlive/2025/bin/x86_64-linux` - **链接图片目录**:工具栏「复制链接」存放图片链接的目录(默认 `~/PicTikZ`,支持 `~` 展开)。链接文件按序号命名(`0001.pdf`、`0002.pdf`…),复制到剪贴板的 `\includegraphics` 命令使用此处填写的目录,见[复制链接](#复制链接) - PNG DPI(72–1200,默认 300) - 代码字体大小(8–48,默认 10) - 界面字体大小(8–48,默认 10)— 影响左栏分类树、缩略图名称及全局界面字体 > **提示**:桌面环境(尤其是 Wayland/systemd 会话)启动 GUI 程序时的 `PATH` 往往比终端里的精简,可能不含 `/usr/local/texlive/.../bin`。若启动时提示「未找到依赖工具 xelatex」,在此处填入 TeX Live 的 `bin` 目录即可(无需登出或修改系统环境)。 **快捷键设置**: - 全部 8 项操作均可自定义键序列 - 清空键序列 = 禁用该快捷键 - 按 Delete 键或点击清除按钮可清空 **行为设置**: - **保存后自动编译** — 开启后点击保存按钮(或按保存快捷键)时自动触发编译并刷新 PDF 预览,无需手动点击"编译预览"。默认开启。 - **编译线程数** — 设置批量预览时并行编译的线程数(1–32,默认 6)。每个线程独立创建 LaTeX 编译器实例,互不干扰。 - **过长代码自动换行** — 开启后过长的代码行在编辑器内自动软换行显示,无需横向滚动;折行产生的续行在左侧行号栏以 `↳` 标记,便于区分新行与续行。默认开启。 - **括号配对高亮** — 开启后光标在 `{}`、`[]`、`()` 旁边时高亮显示与之配对的括号(蓝色背景),找不到配对则以红色警示;选中单个括号字符同样触发。支持跨行嵌套、混合括号类型。默认关闭。 - **开机自启动(启动后隐藏到系统托盘)** — 开启后在 `~/.config/autostart/` 写入 `hitikz.desktop`(`Exec=... --hidden`),登录后程序静默驻留系统托盘,不弹出主窗口;关闭则删除该自启动条目。旧版(缺少 `--hidden`)的自启动条目会在程序启动时自动原地升级。 - **编译状态指示** — 状态栏左侧显示编译结果(绿色"编译成功" / 红色"编译失败,详见日志"),3 秒后自动消失 **模板管理**: - 左侧列表展示所有 `.tex` 模板 - 右侧代码编辑区可编辑选中模板 - +/- 按钮创建 / 删除模板 - 模板中必须包含 `%%% TIKZ_CODE_HERE %%%` 占位符 **工具**: - **生成所有预览** — 多线程并行遍历全部片段编译生成 PDF + 缩略图 PNG(线程数由设置控制,每片段 30 秒超时,路径计算在主线程预完成确保线程安全,状态栏实时进度)。编译完成后自动弹出报告窗口,统计成功/失败数量,列出失败片段详情及编译错误 - **重置所有内容** — 删除所有用户数据,需输入"确定重置"二次确认(高危操作) --- ## 命令行构建 ```bash # 基本构建(自动检测 KGlobalAccel) cmake -B build cmake --build build -j$(nproc) # 构建并运行 ./build/hitikz # 命令行打包链接图片到 LaTeX 项目(见「打包链接图片到项目」) ./build/hitikz pack course.tex pics # 运行测试 cd build && ctest --output-on-failure # 安装 / 卸载(详见「安装与卸载」) sudo cmake --install build sudo cmake --build build --target uninstall ``` CMake 选项: | 选项 | 默认值 | 说明 | |------|--------|------| | `WITH_KGLOBALACCEL` | ON | 启用 KDE KGlobalAccel | | `WITH_QHOTKEY` | ON | KGlobalAccel 不可用时回退 QHotkey | | `CMAKE_INSTALL_PREFIX` | `/usr/local` | 安装前缀(用户自编译程序的惯用位置) | --- ## 项目架构 > 为便于维护,多个体量较大的源文件已按职责拆分为多个翻译单元(共用同一头文件,C++ 允许类成员函数实现分散在多个 `.cpp` 中)。 ``` src/ ├── main.cpp # 入口(`pack` 子命令分发到命令行打包模式;GUI 路径含 QApplication 初始化、`--hidden`/`--minimized` 命令行参数、托盘常驻语义 quitOnLastWindowClosed(false)、旧自启动条目迁移;版本号由 APP_VERSION 宏注入) │ │ # ── 主窗口(共用 mainwindow.h,按职责拆分)── ├── mainwindow.h # MainWindow 类声明 ├── mainwindow.cpp # 核心:窗口框架、UI 搭建、信号连接、片段加载/保存 ├── mainwindow_internal.h # 各实现单元共用的内部常量 ├── mainwindow_tabs.cpp # 多标签页管理(含 TabUiState 标签页间元数据隔离) ├── mainwindow_compile.cpp # 编译流程、日志格式化、预览持久化、批量生成 ├── mainwindow_params.cpp # 参数化系统 ├── mainwindow_shortcuts.cpp # 快捷键与全局热键 ├── mainwindow_drafts.cpp # 自动保存与草稿恢复(含标签页隔离的 UI 状态持久化;恢复对话框见 draft_recovery_dialog) ├── mainwindow_links.cpp # 「复制链接」:预览 PDF 链接到共享图片目录 + 剪贴板 \includegraphics 命令 │ │ # ── 左栏组件(共用 search_panel.h)── ├── search_panel.h / search_panel.cpp # 核心:搜索框、分类树(前缀边界感知,`数学` 不误包含 `数学分析`)、缩略图 ├── search_panel_tags.cpp # 标签过滤器 ├── search_panel_menus.cpp # 右键菜单与拖拽 │ │ # ── 数据层(共用 snippet_manager.h)── ├── snippet_manager.h / snippet_manager.cpp # 核心 CRUD、JSON、分类、缓存、批量操作 ├── snippet_manager_search.cpp # 模糊搜索(双字索引)与分类统计 ├── snippet_manager_io.cpp # 存档导入/导出(tar.gz) │ │ # ── 编译引擎(共用 latex_compiler.h)── ├── latex_compiler.h / latex_compiler.cpp # 核心:编译流程、取消、行号映射 ├── latex_compiler_wrap.cpp # 模板加载与代码包装、元数据注释头生成(%% name/description/tags) ├── latex_compiler_extract.cpp # 自定义命令抽取(40+ 类定义命令,遇不完整定义安全跳过不中断解析)、元数据注释头解析与移除 ├── latex_compiler_convert.cpp # PNG/SVG 转换与工具可用性检测 │ ├── code_editor.h / .cpp # 编辑器(行号+续行 ↳ 标记、当前行/选中词高亮、自动缩进、过长行换行、括号自动配对(含行内公式 `$…$`)、补全/高亮器集成) ├── tikz_highlighter.h / .cpp # TikZ/LaTeX 语法高亮(14 条正则规则 + 花括号深度感知的跨行选项括号 + 跨行 key=value + 6 类用户定义动态高亮) │ │ # ── 智能代码补全(共用 tikz_completer.h)── ├── tikz_completer.h / tikz_completer.cpp # 核心:补全触发、按键处理、跨行上下文回溯、花括号感知的 key 提取 ├── tikz_completer_context.cpp # 上下文检测(13 种上下文) ├── tikz_completer_models.cpp # 补全模型构建与更新(环境/命令/库三级过滤 + 用户定义 + 智能值提示) │ │ # ── 结构化关键词库(共用 tikz_keywords.h)── ├── tikz_keywords.h # TikzKeywordDB 类声明 ├── tikz_keywords.cpp # DB 方法(filter / find / names / valueHints ...) ├── tikz_keywords_data.h / .cpp # 注册入口 registerAllBuiltins + 共用辅助函数 ├── tikz_keywords_basic.cpp # 颜色/线宽/线型/箭头/形状/图案/装饰/锚点/处理器/PGF路径/库/坐标系/环境 ├── tikz_keywords_commands.cpp # 命令 + CircuiTikZ 路径元件(473 个,含 full/empty/stroke 二极管族、inline 端口)与用户命令 ├── tikz_keywords_options.cpp # 通用选项 ├── tikz_keywords_pgfplots.cpp # 3dplot / pgfplots / 杂项形状选项 ├── tikz_keywords_extended.cpp # CircuiTikZ 形状(141 个,含 transformer/transformer core/gyrator 等四极子 + potentiometershape)/选项(双极子标注 i/v/f/l/a 全变体、元件修饰键、25 类 fill|scale|thickness 样式矩阵、元件级便利键、用户级样式键,均对照 1.7.1 源码)、tikz-cd、chemfig、tikz-feynman、graphs、pgfplots 扩展等 │ #(合计约 2900+ 条目:CircuiTikZ 元件473+形状141+锚点56 + tkz-euclide 261 + chemfig + tikz-feynman + tikz-cd + 形状~120 + 装饰 ~30 + 装饰子选项 35+ + 库门控键 80+ + PGF键路径30+) ├── tikz_document_state.h / .cpp # 文档状态追踪(范围栈、库解析、`\usepackage` → 活动库映射(circuitikz/tkz-euclide/tikz-cd/chemfig/tikz-feynman/physics/siunitx/pgfplots/tikz-3dplot,代码/元数据/LaTeX 模板三路共用同一映射表)、用户样式/坐标/节点/pic/foreach(含可选参数)/颜色/命令/命名路径(name path)/交点名(by=) 解析) ├── tikz_words.h # TikZ 词库兼容层(委托到 TikzKeywordDB,含 tikzPathOperations 精选路径操作集合、latexPackages 常用宏包名) ├── comma_list_completer.h # 逗号分隔字段(额外宏包 / TikZ库)的分段自动补全器(仅补全最后一段,保留前序条目;弹窗按字段强调色着色 + 彩色圆点条目标记 + 等宽字体,明暗主题自适应) ├── flow_layout.h / flow_layout.cpp # 流式布局组件(支持自动换行,用于标签过滤器) ├── pdf_preview_widget.h / .cpp # PDF 预览组件(缩放/平移/适应模式,从 MainWindow 抽出) ├── settings_dialog.h / .cpp # 设置面板(路径/行为/快捷键/开机自启动/模板管理/工厂重置) ├── autostart_manager.h / .cpp # XDG 自启动条目管理(写入/移除 ~/.config/autostart/hitikz.desktop,Exec 带 --hidden;旧条目自动迁移) ├── draft_recovery_dialog.h / .cpp # 草稿恢复对话框(勾选恢复 / 全部丢弃(带确认)/ 稍后处理;独立结果码,可单元测试) ├── snippet_properties_dialog.h / .cpp # 片段属性编辑对话框(含图片管理:导入/粘贴/查看/替换/删除;超链接图片状态与删除) ├── link_manager.h / .cpp # 「复制链接」图片链接管理(目录配置、序号分配与空缺填补、符号链接创建/删除、\includegraphics 命令生成) ├── project_packager.h / .cpp # 命令行 `hitikz pack`:扫描文档引用、按需复制链接图片进项目目录(跳过/覆盖编号、01/001/0001 命名、缺失引用报错)、完整源码与关联图片复制、\includegraphics 引用路径改写、参数解析与 CLI 入口 ├── kde_global_shortcut.h / .cpp # KDE KGlobalAccel 全局快捷键(或 QHotkey 回退) resources/ ├── templates/ # 出厂模板(3 个极简模板) │ ├── default_math.tex # tikz, amsmath, xcolor │ ├── default_physics.tex # tikz, xcolor │ └── default_circuit.tex # tikz, xcolor, circuitikz, preview └── presets/ # 出厂预置片段(120 个) └── / ├── meta.json └── snippet.tex tests/ ├── test_snippet_manager.cpp # CRUD 操作 + ZIP 导入/导出测试 ├── test_snippet_images.cpp # 图片管理(字母序号命名、增删替换、JSON 容错、存档携带图片、复制文件、编译目录图片拷贝、属性对话框图片列表与剪贴板粘贴、超链接图片状态与删除) ├── test_link_manager.cpp # 复制链接(默认/自定义目录与 ~ 展开、\includegraphics 命令、序号空缺填补、失效链接保留序号、符号链接创建/替换/删除) ├── test_project_packager.cpp # 命令行 pack(参数解析与错误、文件/目录/通配符展开、01/001/0001 命名、按需复制只处理被引用图片、跳过/覆盖编号与提示、引用改写仅动路径、多文件多引用、无扩展名引用、源码复制与 linkedPdf 回退、错误路径、设置默认链接目录、CLI 退出码) ├── test_latex_compiler.cpp # 编译 + PNG/SVG 转换测试 ├── test_search.cpp # 模糊搜索算法 + 分类 + 标签过滤测试 ├── test_packages_libraries.cpp # 宏包/TikZ库解析与模板注入测试 ├── test_highlighter_regex.cpp # 语法高亮正则表达式正确性测试(数学模式、注释、命令等) ├── test_multitab.cpp # 多标签页功能测试(创建/切换/关闭/去重)+ 编辑器过长行换行切换 + 撤销/重做按钮状态 + 模板宏包激活补全 + 元数据补全弹窗样式 ├── test_draft_recovery.cpp # 草稿格式完整性 + 目录扫描测试 ├── test_draft_recovery_dialog.cpp # 草稿恢复对话框(加载/过滤/勾选、全部丢弃按钮接线与独立结果码) ├── test_autostart.cpp # 自启动条目写入/移除/迁移(--hidden 升级、Exec 引号、无 Exec 行安全跳过) ├── test_tex_import.cpp # .tex 文件导入代码提取测试 ├── test_params.cpp # 参数声明解析与替换测试 ├── test_fixes.cpp # 关键功能验证(行号正则、注释优先级、QProcess、数据流) ├── test_completer.cpp # 补全词库完整性 + detectContext 13 种上下文 69 用例(含 \end{}、花括号内 = 值补全、坐标系 cs: 键)+ 箭头大小写双变体 + 定位键坐标补全 + 装饰完整列表 + 库门控 + label/pin 方位 + font/node font 字体值(含样式体内)+ to path 与坐标宏 + graphs/matrix 选项 + of= 命名路径 + 坐标系名/键补全(3d/calc/perspective 门控)+ 含空格补全上屏无多余字符 + 已完成值内嵌括号对后 cs: 键补全 + CircuiTikZ 标注/修饰/类样式/用户命令审计 + CircuiTikZ/tikz-cd/tkz-euclide/chemfig/tikz-feynman 源码一致校验 ├── test_document_state.cpp # 文档状态追踪(23 个用例:范围/库/样式/坐标/pic/foreach(含可选参数)/颜色/\usepackage 激活 physics·siunitx·pgfplots/节点 name= 选项语法提取/命名路径 name path/by= 交点名提取/LaTeX 模板内容激活补全库/元数据宏包映射统一) └── test_enhanced_highlighter.cpp # 增强语法高亮(14 个用例:PGF路径/处理器/用户定义名/key=value花括号深度/跨行选项/综合) ├── test_review_fixes.cpp # 数据一致性与交互逻辑(saveSnippet 数据一致性、转义括号匹配、虚拟节点拖拽禁用、分类树选择恢复、子分类跟随移动、自身/后代拖放拒绝) # ── 打包与安装 ── cmake/ └── cmake_uninstall.cmake.in # uninstall 目标使用的模板(按 install_manifest.txt 卸载) hitikz.desktop # 桌面入口(Exec=hitikz,Icon=hitikz) hitikz.svg # 应用图标(scalable) ``` ### 核心类关系 ``` MainWindow ├── SearchPanel ← SnippetManager │ ├── QLineEdit 搜索框 │ ├── FlowLayout 标签过滤器(流式按钮、2行折叠、弹出对话框) │ ├── QTreeView 分类树(含"未分类"节点) │ ├── QSplitter 可拖动分隔条(分类树 / 缩略图) │ └── QListView 缩略图网格(ExtendedSelection 多选) ├── QTabWidget 多标签页容器 │ ├── CodeEditor 代码编辑器(每个标签页一个实例) │ │ ├── TikzHighlighter 语法彩色高亮(14 条规则 + 用户定义) │ │ ├── TikzCompleter 智能补全(13 种上下文 + 三级过滤 + 智能值提示 + 上下文感知命令 + 坐标系 cs: 补全 + CircuiTikZ/tkz-euclide 支持 + 环境自动闭合) │ │ ├── TikzDocumentState 文档状态追踪 │ │ └── LineNumberArea 行号显示 │ └── ...(更多标签页) ├── QPlainTextEdit 编译日志面板(精简过滤、行号映射、彩色格式化) ├── QSplitter(垂直) PDF 预览与元数据区可调分割 │ ├── PdfPreviewWidget PDF 矢量预览(缩放/平移/适应,独立组件) │ └── QScrollArea 元数据编辑表单 + 参数控件 ├── LatexCompiler 编译引擎(xelatex + pdftocairo/inkscape SVG转换 + 嵌套括号解析 + 行号映射 + 自定义命令抽取/注入) ├── SnippetManager 数据层(JSON 读写、双字索引搜索、分类缓存、批量操作) ├── LinkManager 「复制链接」图片链接管理(目录配置、序号空缺填补、符号链接、\includegraphics 命令) ├── ProjectPackager 「hitikz pack」命令行打包(链接图片复制、编号分配、源码复制、引用改写;main.cpp 分发) ├── SettingsDialog 设置面板(路径/快捷键/模板管理/工厂重置) └── KdeGlobalShortcut KDE 全局快捷键(或 QHotkey 回退) ``` ### 编辑器信号关键路径 ``` 光标移动 → highlightCurrentLine() → ExtraSelection(当前行 + 选中词全部出现位置) 用户输入 → keyPressEvent() → handleCompletionKey()(Enter/Tab 上屏,↑↓ 导航;`\begin{env}` 完成后自动插入 `\end{env}`) → 括号自动配对(`{}`/`[]`/`()`/`$$` 双符插入、选中包裹、闭合跳过、空对退格删除) → QPlainTextEdit::keyPressEvent() → tryComplete()(上下文检测 → 切换 Completer) → parseParams()(扫描 @param → 更新参数控件 + 参数补全词库) 文本变更 → textChanged → (m_loadingDepth == 0) → onCurrentSnippetChanged() → parseParams() → autoSaveTimer(180s) → performAutoSave() 标签切换 → onTabChanged() → setEditorForTab() → loadPreview + loadMetadata + parseParams() ``` --- ## 测试 项目包含十九套自动化测试(通过 CTest 运行): | 测试 | 内容 | |------|------| | `test_snippet_manager` | 片段创建/读取/更新/删除,loadCode,renameCategory,compileCommand/sortOrder JSON 序列化,linkedPdf 字段往返与旧版无字段容错,ZIP 导入/导出,reorderSnippets,categoryOrder 保存/加载 | | `test_snippet_images` | 图片管理:字母序号命名(a–z、aa–zz)、受支持扩展名检测、图片添加/替换/删除(含序号复用与跳过占用、替换扩展名更新、缺失源文件回退)、meta.json `images` 字段往返与旧版无字段容错、存档导出/导入携带图片(linkedPdf 导入时清除)、片段间图片文件复制、编译临时目录图片拷贝、属性对话框图片列表/按钮状态(无选中时灰色禁用、选中后启用)/剪贴板图像粘贴与 Ctrl+V 快捷键/超链接图片状态与删除(10 组测试) | | `test_link_manager` | 复制链接:默认/自定义链接目录(`~` 展开、尾斜杠归一、空值回退默认)、`\includegraphics` 命令生成、序号空缺填补(0001/0003/0004→0002)、非序号文件忽略、失效符号链接保留序号、符号链接创建/内容更新可见/覆盖替换/删除与序号释放、缺失源文件失败(5 组测试) | | `test_project_packager` | 命令行 `hitikz pack`:参数解析(默认值、全选项、`--opt=值` 形式、未知选项/缺值/非法格式/位置参数数量/空目录报错、`--help`);TeX 参数展开(单文件/目录/`*`/`?` 通配符/无匹配);链接文件收集(数字排序、非数字忽略、失效链接计入);01/001/0001 编号格式(含超宽自然增长);`\includegraphics` 改写(选项保留、星号变体、选项前空格、注释行不动、`\%` 转义百分号不算注释、同一图片多处改写、未映射路径不动、空内容);不覆盖模式空缺填补(已有 01/03 → 新图取 02/04,打印跳过提示,原文件保留);覆盖模式顺序编号(打印覆盖提示、未引用文件不覆盖);三种命名格式端到端(未引用图片不复制);按需复制(只复制被引用的图片、未引用不动且不占号、编号仅按被复制图片分配、缺失引用报错且不改写、文档未引用任何图片为成功空操作);无扩展名引用(`0001` 识别为 `0001.pdf` 并改写补全扩展名,缺失时不动);一图多文件全改写(目录参数);源码复制(完整文档含元数据头、关联图片 `001_a.png` 前缀命名、文档内引用同步改名、符号链接目标解析与 meta.json `linkedPdf` 回退两条路径);错误路径(TeX 缺失/空通配符/链接目录缺失/失效链接复制失败且引用不动);默认链接目录读取程序设置(保存/恢复 QSettings);CLI 退出码(0 成功、1 运行时错误、2 用法错误,stdout/stderr 分流)(16 组测试) | | `test_latex_compiler` | xelatex 可用性检测,基本编译,PDF 生成,PNG 转换,SVG 转换,编译日志验证,自定义命令抽取(覆盖 14 类定义命令)、含分隔符参数的 `\def` 与参数后换行的 `\newcommand` 抽取、不完整定义的安全跳过、注释随命令迁移(前置注释块、行尾注释、图内注释保留)、析构回收转换子进程、compileCommand 自定义引擎编译与 lastFullCommand 验证(64+ 项测试) | | `test_search` | 精确匹配、子序列匹配、连续加分、中文搜索、标签过滤、分类统计 | | `test_packages_libraries` | 宏包字符串解析(含嵌套括号选项),TikZ 库解析,模板注入正确性,往返序列化 | | `test_highlighter_regex` | 数学模式 `$...$`、`\(...\)`、`\[...\]` 正则表达式匹配验正 | | `test_multitab` | 多标签页功能:创建/切换/关闭标签页、重复打开去重、关闭前未保存检查、编辑器过长行自动换行切换、元数据脏标记检测、切换标签页元数据隔离与标题正确性、UI 库栏改动即时同步到编辑器补全(`circle through` 等)、`$` 行内公式自动配对(插入/包裹选中/跳过闭合/空对退格)、`{|}` 独占行回车三行拆分、`Tab`/`Shift+Tab` 多行块缩进与反缩进、标签过滤器状态管理(标签移除/集合不变/标签栏稳定性)、额外宏包/TikZ库字段的逗号感知分段补全器(含彩色圆点标记与双弹窗强调色断言)、撤销/重做按钮状态管理(零标签页置灰、编辑后启用、撤销/重做到头置灰、跨标签页状态隔离与恢复、代码加载后初始置灰)、模板宏包激活补全(default_circuit 片段端到端激活 circuitikz 库门控形状,含反向门控校验)、复制链接端到端(首次分配 0001 并记录 linkedPdf、二次点击复用、删除后重建、空缺填补 0002、无预览 PDF 拒绝创建)、复制文档元数据注释头(名称/简介/标签、空字段不输出注释行)、复制文件 000.tex 元数据头(含多行简介)、剪贴板导入元数据解析与「导入文件」默认名 | | `test_draft_recovery` | 草稿文件格式完整性(全字段 JSON 读写往返、空代码过滤、目录扫描) | | `test_draft_recovery_dialog` | 草稿恢复对话框:目录加载(损坏/空代码过滤、无名回退)、默认全选/全选/取消全选按钮、全部丢弃按钮功能与结果码、恢复所选/稍后处理逻辑 | | `test_autostart` | 开机自启动条目:desktop 文件内容(--hidden、含空格路径引号、KDE 排序提示)、启用/停用/幂等、旧条目迁移(原地补 --hidden、二次迁移零改动、无 Exec 行不改写) | | `test_tex_import` | .tex 文件导入代码提取(三段式解析)及宏包/TikZ 库声明解析、元数据注释头生成(空字段跳过、多行简介逐行输出)、解析与移除(多行拼接、正文同形注释不解析、tikzpicture 单文件解析、单 % 兼容、同字段首条为准)、往返一致 | | `test_params` | 参数声明正则解析与 `@@var@@` 替换正确性(单参数、多参数、负数、零值) | | `test_fixes` | 关键功能验证:行号解析、注释优先级处理、代码包装、进程启动检测、数据流状态、编译配置、文件原子操作、草稿清理、路径安全检查、导入目录管理(11 项测试) | | `test_completer` | 补全词库完整性(去重、条目数量、TeX 条件原语含 `\fi`/`\ifcase` 等)、detectContext 13 种上下文检测(69 用例含 `\end{}`、花括号内 `=`、坐标系 `cs:`、方括号内 `font=\Large` 等值补全)、箭头大小写双变体、定位键坐标补全、PGF 键处理器/值提示/颜色值补全、key 提取的花括号/中括号感知、跨行上下文回溯、装饰完整 27 名 eq 补全、锚点源码准确性、库门控、label/pin/font/node font 值补全、`to path`/`\tikztostart`/graphs/matrix 选项、`of=` 命名路径、坐标系名与 cs: 键补全、含空格补全值上屏;CircuiTikZ/标准 TikZ/数学函数/装饰/physics·siunitx/pgfplots/tikz-cd·tkz-euclide·chemfig·tikz-feynman 各词库组源码一致性校验 | | `test_document_state` | 文档状态追踪:范围栈检测、库解析、用户样式(含空格名)/坐标/节点/pic名(含 `name=` 选项语法)/路径操作坐标/foreach变量(含空格多变量、可选方括号参数)/颜色/命令解析(含 `\pgfmathsetmacro`/`\pgfmathsetlengthmacro`/`\pgfmathtruncatemacro`)、命名路径与 `by=` 交点名提取、环境名查询、片段库注入、`\usepackage` 激活补全库、LaTeX 模板内容激活、元数据宏包映射统一(24 个测试用例) | | `test_enhanced_highlighter` | 增强语法高亮:PGF路径/键处理器/库规则,用户样式/节点名/foreach变量高亮检测,key=value分色(含花括号深度隔离),跨行选项括号高亮,多行注释,综合测试,foreach空格分隔变量,注释保护检查(14 个测试用例) | | `test_review_fixes` | 数据一致性与交互逻辑:saveSnippet 数据一致性、LaTeX 转义括号处理、分类树交互行为(虚拟节点拖拽控制、子分类选择恢复、分类拖动与子分类跟随、拖拽有效性检查) | 运行测试: ```bash cd build && ctest --output-on-failure ``` 全部 19 套测试通过,方可提交。 --- ## 技术栈 | 技术 | 用途 | |------|------| | **C++17** | 核心语言 | | **Qt 6** | Widgets (UI), Gui (QSyntaxHighlighter), Pdf (PDF 渲染), PdfWidgets (QPdfView) | | **CMake** | 构建系统 | | **KF6GlobalAccel** | KDE 原生全局快捷键 | | **QHotkey** (fallback) | 非 KDE 环境的全局快捷键 | | **XeLaTeX** | LaTeX → PDF 编译 | | **pdftocairo** | PDF → PNG / SVG 转换(默认) | | **Inkscape** | PDF → SVG 转换(备选,可在设置中切换) | | **JSON** | 片段元数据格式 | | **tar / unzip** | 存档导入/导出 | --- ## 已知问题 ### 1. SVG 剪贴板粘贴到 Inkscape 样式变化 通过工具栏"复制SVG"将 SVG 粘贴到 Inkscape 后图片样式发生变化,而导出为 SVG 文件再在 Inkscape 中打开则正常。此问题与使用的转换工具(pdftocairo 或 Inkscape)无关,剪贴板粘贴路径本身会导致样式丢失。 - **现象**:粘贴后的图形颜色、线条或布局与原始预览不一致 - **临时规避**:使用"导出为 SVG 图片"保存为文件后,在 Inkscape 中通过"文件 → 打开"或"文件 → 导入"打开该文件 ### 2. 部分不规范的 TikZ 代码可能导致编译卡死 某些格式错误的 TikZ 代码(如递归定义、无限循环等)可能让 XeLaTeX 陷入死循环。此时可点击工具栏"强制结束"按钮立即中断编译进程,避免计算机风扇狂转。 ### 3. 多行选项中个别 token 的颜色会被后续规则覆盖 `applyOptionBrackets` 先将跨行 `[...]` 整体标记为选项色(青色),但后续正则规则(如命令规则匹配 `\line`、`\width`)会覆盖个别 token 的颜色。这属于优先级设计——特定语法元素(命令、数字等)的颜色优先于选项底色。每个连续行的闭合 `]` 和行间选项整体识别不受影响。