news 2026/9/7 23:21:01

Zed 语言扩展开发指南:从 config.toml 到 Tree-sitter 查询与 LSP 集成

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Zed 语言扩展开发指南:从 config.toml 到 Tree-sitter 查询与 LSP 集成

Zed 语言扩展开发指南:从 config.toml 到 Tree-sitter 查询与 LSP 集成

【免费下载链接】zedCode at the speed of thought – Zed is a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter.项目地址: https://gitcode.com/GitHub_Trending/ze/zed

Zed 是一套开放的语言基础设施:编辑器自身内置的语言支持与第三方扩展语言包共享同一套“语言元数据 + Tree-sitter 语法 + LSP 服务器”三层架构。本文以 Zed 仓库中官方文档 languages.md 为骨架,结合仓库内真实扩展(HTML、GLSL、Test Extension)讲解如何为一种新语言编写config.toml、注册 Grammar、编写各类 Tree-sitter.scm查询,以及如何接入语言服务器与语义化 Token(Semantic Tokens)。读完你可以独立为 Zed 打造一个具备语法高亮、缩进、大纲、括号匹配与 LSP 补全能力的完整语言扩展。

语言支持的四个组成部分

Zed 中一种语言的支持由四层组成,扩展开发需要逐一提供或配置:

  1. 语言元数据与配置(Language metadata and configuration)——即config.toml,声明语言名称、语法、文件后缀、注释风格、缩进等信息;
  2. 语法(Grammar)——基于 Tree-sitter 解析库的语法定义,在extension.toml中单独注册;
  3. 查询(Queries)——一系列.scm(Tree-sitter Query)文件,用于在语法树上实现高亮、缩进、大纲等功能;
  4. 语言服务器(Language servers)——通过 LSP 协议接入第三方服务器,提供补全、跳转等高级能力。

语言元数据:languages/<name>/config.toml

每种 Zed 支持的语言必须在扩展的languages目录下拥有一个子目录,子目录内必须包含名为config.toml的文件,其基本结构如下:

name = "My Language" grammar = "my-language" path_suffixes = ["myl"] line_comments = ["# "]

字段含义如下:

  • name(必填):人类可读的名称,会显示在语言选择(Select Language)下拉框中。
  • grammar(必填):Grammar 名称。Grammar 是单独注册的(详见下文),此字段只是引用其名字。
  • path_suffixes:与该语言关联的文件后缀数组。与 settings 中的file_types不同,这里不支持 glob 模式,只能写具体后缀。
  • line_comments:标识该语言行注释的字符串数组。它服务于editor::ToggleComments键位绑定,用于切换整行注释。
  • tab_size:缩进/制表符尺寸,默认4
  • hard_tabs:是否用制表符缩进,true表示 Tab,默认false(空格)。
  • first_line_pattern:一个正则表达式,可与path_suffixes(或 settings 中的file_types)配合,按文件首行内容匹配语言。Zed 就用它通过首行的 shebang 行来识别 Shell 脚本。
  • debuggers:标识该语言可用调试器的字符串数组。在调试器的“新建进程(New Process Modal)”弹窗中,Zed 会按照该数组的顺序排列可用调试器。

真实示例:HTML 扩展的 config.toml

仓库自带的 HTML 扩展配置 展示了上述字段之外的更多可配置项,是学习config.toml的最佳参照:

name = "HTML" grammar = "html" path_suffixes = ["html", "htm", "shtml"] autoclose_before = ">})" block_comment = { start = "<!--", prefix = "", end = "-->", tab_size = 0 } wrap_characters = { start_prefix = "<", start_suffix = ">", end_prefix = "</", end_suffix = ">" } brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, { start = "(", end = ")", close = true, newline = true }, { start = "\"", end = "\"", close = true, newline = false, not_in = ["comment", "string"] }, { start = "<", end = ">", close = false, newline = true, not_in = ["comment", "string"] }, { start = "!--", end = " --", close = true, newline = false, not_in = ["comment", "string"] }, ] completion_query_characters = ["-"] prettier_parser_name = "html" [overrides.default] linked_edit_characters = ["-"]

从该配置可以归纳出文档正文未展开、但同样可用的键(这些键同样以内置语言为参考目标,官方在 languages.md 中以注释形式列出待补文档):autoclose_beforebrackets(元素含start/end/close/newline/not_innot_in可限定不出现在如commentstring等作用域内)、block_comment(多行注释的起止与前缀)、wrap_characters(成对包裹字符)、completion_query_charactersprettier_parser_namecode_fence_block_nameword_characterscollapsed_placeholderauto_indent_on_pasteauto_indent_using_last_non_empty_line以及[overrides.<scope>]作用域级覆盖(如 HTML 在[overrides.default]下配置linked_edit_characters)。

注册 Tree-sitter Grammar:extension.toml 中的[grammars.*]

Zed 使用 Tree-sitter 解析库提供内置的语言级特性。许多语言都有现成语法,也可以自行开发语法(Tree-sitter 官方写作指南提供了从零编写语法的路径)。前面提到,扩展中定义的每种语言必须指定用于解析的 Grammar 名称,而这些 Grammar 要在扩展根目录的extension.toml单独注册,例如:

[grammars.gleam] repository = "https://github.com/gleam-lang/tree-sitter-gleam" rev = "58b7cac8fc14c92b0677c542610d8738c373fa81"
  • repository:指定加载 Grammar 的仓库地址;
  • rev:要使用的 Git 修订号,例如某个 Git 提交的 SHA。

正在本地开发扩展时,若想从本机文件系统加载 Grammar,可将repository写成file://URL。一个扩展可以引用多个 Tree-sitter 仓库,从而提供多种 Grammar。

需要说明的是:本仓库的官方示例使用了rev键,而仓库内实际的 HTML 与 GLSL 扩展在 extension.toml、GLSL extension.toml 中填写的是commit字段(同样是提交 SHA),两种字段名均指向同一“Git 修订号”语义,书写时可参照官方文档使用rev

Tree-sitter Queries:驱动编辑器核心功能的查询文件

Zed 借助 Tree-sitter 查询语言,在语法树上实现多项功能:

  • 语法高亮(Syntax highlighting)
  • 括号匹配(Bracket matching)
  • 代码大纲/结构(Code outline/structure)
  • 自动缩进(Auto-indentation)
  • 代码注入(Code injections)
  • 语法作用域覆盖(Syntax overrides)
  • 文本脱敏(Text redactions)
  • 可运行代码检测(Runnable code detection)
  • 选择类/函数等代码块(Selecting classes, functions, etc.)

下文以 JSON 语法为例逐一展开每种查询文件的写法。

语法高亮:highlights.scm

Tree-sitter 中,highlights.scm文件定义某种语法的着色规则。JSON 的示例:

(string) @string (pair key: (string) @property.json_key) (number) @number

该查询分别标记了字符串、对象键与数字用于高亮。主题支持的完整 capture 列表如下:

Capture描述
@attribute捕获属性
@boolean捕获布尔值
@comment捕获注释
@comment.doc捕获文档注释
@constant捕获常量
@constant.builtin捕获内置常量
@constructor捕获构造函数
@embedded捕获嵌入内容
@emphasis捕获强调文本
@emphasis.strong捕获加粗强调文本
@enum捕获枚举
@function捕获函数
@hint捕获提示
@keyword捕获关键字
@label捕获标签
@link_text捕获链接文本
@link_uri捕获链接 URI
@number捕获数值
@operator捕获运算符
@predictive捕获预测性文本
@preproc捕获预处理指令
@primary捕获主元素
@property捕获属性/字段
@punctuation捕获标点
@punctuation.bracket捕获括号
@punctuation.delimiter捕获分隔符
@punctuation.list_marker捕获列表标记
@punctuation.special捕获特殊标点
@string捕获字符串字面量
@string.escape捕获字符串中的转义字符
@string.regex捕获正则表达式
@string.special捕获特殊字符串
@string.special.symbol捕获特殊符号(如 Ruby symbol)
@tag捕获标签(如 HTML 标签)
@tag.doctype捕获文档类型声明(如 HTML doctype)
@text.literal捕获字面文本
@title捕获标题
@type捕获类型
@type.builtin捕获内置类型
@variable捕获变量
@variable.special捕获特殊变量
@variable.parameter捕获函数/方法参数
@variant捕获变体
Fallback captures:同节点的回退高亮

单个 Tree-sitter 模式可以在同一节点上指定多个 capture 以实现回退高亮。Zed从右向左解析:先尝试最右侧的 capture,若当前主题没有它的样式,则回退到左侧下一个 capture,依此类推。例如:

(type_identifier) @type @variable

这里 Zed 会先从主题解析@variable:若主题为@variable定义了样式则使用它,否则回退到@type。当某语言希望提供一个并非所有主题都支持的首选高亮、同时又想回退到多数主题都有的通用 capture 时,这种写法非常有用。

括号匹配:brackets.scm

brackets.scm定义可配对的括号。JSON 的示例:

("[" @open "]" @close) ("{" @open "}" @close) ("\"" @open "\"" @close)
Capture描述
@open捕获开括号、开大括号与引号
@close捕获闭括号、闭大括号与引号

Zed 利用这些规则实现匹配括号高亮:为每对括号渲染不同颜色(“彩虹括号”),并在光标位于括号对内部时高亮它们。若要关闭某个条目的彩虹括号着色,可在对应brackets.scm条目中追加:

(("\"" @open "\"" @close) (#set! rainbow.exclude))

仓库中 HTML 的 brackets.scm 即按同样思路为 HTML 标签与引号定义了@open/@close捕获。

代码大纲/结构:outline.scm

outline.scm定义代码大纲的结构。JSON 的示例捕获对象键生成大纲条目:

(pair key: (string (string_content) @name)) @item
Capture描述
@name捕获对象键的内容(即大纲条目显示名)
@item捕获整个键值对(即大纲条目本体)
@context捕获为大纲条目提供上下文的元素
@context.extra捕获大纲条目的额外上下文信息
@annotation捕获注解大纲条目的节点(文档注释、属性、装饰器等)1

自动缩进:indents.scm与基于行模式的缩进规则

indents.scm定义缩进规则,分两种实现路径。

基于语法节点的缩进与反缩进
Capture描述
@indent用捕获的节点定义一个缩进范围
@start将某个@indent范围的起点移动到所捕获节点的末尾
@end将某个@indent范围的终点移动到所捕获节点的开头
@outdent在捕获节点开始处结束最内层的缩进范围

例如缩进整个if_statement节点内容:

(if_statement) @indent

缩进范围从节点起点延伸到终点。

HTML 元素包含开闭标签,若只想缩进二者之间的内容:

(element (start_tag) @start ; 在开标签之后开始缩进 (end_tag)? @end) @indent ; 在闭标签之前结束缩进

else/case后续标签需要与前一个分支对齐(而不是缩进到更深一层)时,可以让其从所在 case 主体反缩进:

(compound_statement (case_statement ":" @start) ; 从 case 主体开始缩进 "}" @end) @indent (compound_statement (case_statement) (case_statement) @outdent) ; 使后续 case 标签对齐

仓库内 HTML 的 indents.scm 正是用@indent/@start/@end组合控制开标签到闭标签之间内容的缩进。

基于行模式的缩进与反缩进

当需要按“行内容”而非语法节点匹配时,可在config.toml中配置以下选项:

Option描述
increase_indent_pattern匹配的行令其下一行缩进一级
decrease_indent_pattern匹配的行反缩进一级,不考虑语法上下文
decrease_indent_patterns匹配的行与某个允许的更早语法结构对齐

例如“行尾以:结尾则下一行缩进”:

increase_indent_pattern = ":\\s*$"

例如“以end开头的行反缩进”:

decrease_indent_pattern = "^\\s*end\\b"
让子句与相关代码块对齐:decrease_indent_patterns+valid_after

decrease_indent_patterns适用于“应与其所属代码块对齐而非无条件左移一级”的行。做法分两步:先在indents.scm中用带命名的@start.<name>捕获标记该代码块的起点:

(if_statement) @start.if

然后在config.toml中把该捕获的后缀名列入valid_after

decrease_indent_patterns = [ { pattern = "^\\s*else\\b", valid_after = ["if"] }, ]

此时以else开头的行会与最近一个“处于相同或更低缩进层级”的@start.if对齐;若找不到匹配的代码块,缩进保持不变。注意:@start.if这类命名捕获只用于标记代码块,与@start不同,它们不会改变@indent的范围。Zed 会按顺序检查规则,命中第一条pattern后即停止,因此较具体的模式应写在较通用的模式之前

代码注入:injections.scm

injections.scm定义一种语言嵌入另一种语言的规则,例如 Markdown 中的代码块、Python 字符串中的 SQL。Markdown 的示例:

(fenced_code_block (info_string (language) @injection.language) (code_fence_content) @injection.content) ((inline) @content (#set! injection.language "markdown-inline"))

该查询识别围栏代码块:捕获 info string 中声明的语言标识与块内内容,并把它们交给对应语言解析;同时捕获行内内容并注入为markdown-inline语言。

Capture描述
@injection.language捕获代码块的语言标识
@injection.content捕获需要按另一种语言处理的内容

注意 JSON 不支持语言注入,因此这里不能再用 JSON 举例。仓库内 GLSL 扩展 也提供了类似机制。

语法作用域覆盖:overrides.scm+[overrides.*]

overrides.scm定义语法作用域(scopes),用于在特定语言结构中覆盖某些编辑器设置。例如语言级设置word_characters控制哪些非字母字符被视为单词的一部分(双击选中变量时生效),JavaScript 中$#是单词字符;另一项语言级设置completion_query_characters控制哪些字符会触发自动补全。当光标位于字符串内时,JavaScript 希望-也能触发补全,于是其overrides.scm包含:

[ (string) (template_string) ] @string

对应 JavaScript 的config.toml

word_characters = ["#", "$"] [overrides.string] completion_query_characters = ["-"]

也可以在指定作用域内禁用某些自动闭合括号。例如阻止字符串内部自动闭合',可把如下内容写入 JavaScript 的config.toml

brackets = [ { start = "'", end = "'", close = true, newline = false, not_in = ["string"] }, # other pairs... ]
作用域范围的包含性

默认情况下overrides.scm定义的范围是排他(exclusive)的:仍以上例而言,若光标位于界定字符串的引号之外string作用域不会生效。有时需要让范围变成包含(inclusive),做法是在查询的 capture 名上加.inclusive后缀。例如 JavaScript 需要在注释中也禁用单引号自动闭合,且注释作用域要延伸到行注释后的换行处,于是其overrides.scm为:

(comment) @comment.inclusive

文本对象:textobjects.scm

textobjects.scm定义按文本对象导航的规则,于 Zed v0.165 加入,目前仅在 Vim 模式下使用。Vim 提供两种文件内导航粒度:用[]等按键的逐“段”移动,以及用]m等的逐“方法”移动。即使语言本身没有函数与类的概念,也可以通过映射获得良好效果:例如 CSS 把一个 rule-set 视为“方法”、把 media-query 视为“类”。含闭包的语言通常不应把闭包当作函数——但这属于尽力而为,因为 JavaScript 之类的语言在语法上并不区分闭包与顶层函数声明。对 C 这类以声明为主的语言,需要提供匹配@class.around@function.around的查询;在没有 inside 捕获时,if/ic文本对象会默认回退到它们。

若不确定textobjects.scm该写什么,可以参考 nvim-treesitter-textobjects 与 Helix 编辑器为多种语言提供的查询,再对照 Zed 内置语言(本仓库的 crates/languages/src)来适配。

Capture描述Vim 模式
@function.around整个函数定义,或文件中等价的一小段[m]m[M]M移动;af文本对象
@function.inside函数体(花括号内部的内容)if文本对象
@class.around整个类定义,或文件中等价的较大片段[[]][]][移动;ac文本对象
@class.inside类定义的内容ic文本对象
@comment.around整段注释(如所有相邻行注释或一个块注释)gc文本对象
@comment.inside注释的内容igc文本对象(较少支持)

示例:

; 只把方法体内含纳入 function (method_definition body: (_ "{" (_)* @function.inside "}")) @function.around ; 为没有函数体的声明匹配 function.around (function_signature_item) @function.around ; 把所有相邻注释合并为一段 (comment)+ @comment.around

文本脱敏:redactions.scm

redactions.scm定义文本脱敏规则。协作与共享屏幕时,Zed 会以脱敏模式渲染某些语法节点,避免泄露敏感数据。JSON 的示例:

(pair value: (number) @redact) (pair value: (string) @redact) (array (number) @redact) (array (string) @redact)
Capture描述
@redact捕获需脱敏的值

该查询将键值对与数组中的数值、字符串标记为脱敏对象。

可运行代码检测:runnables.scm

runnables.scm定义可运行代码的检测规则。以下 JSON 示例可在 package.json 与 composer.json 中检测到可运行脚本:

( (document (object (pair key: (string (string_content) @_name (#eq? @_name "scripts") ) value: (object (pair key: (string (string_content) @run @script) ) ) ) ) ) (#set! tag package-script) (#set! tag composer-script) )

@run捕获指定运行按钮应出现在编辑器的哪个位置。其余捕获(下划线_前缀的除外)在运行代码时会以ZED_CUSTOM_$(capture_name)前缀的环境变量形式暴露出来。

Capture描述
@_name捕获 "scripts" 键
@run捕获脚本名(确定运行按钮位置)
@script同样捕获脚本名(供不同用途使用)

Language Servers:接入 LSP

Zed 通过语言服务器协议(LSP)提供更高级的语言支持。一个扩展可以提供任意数量的语言服务器。

声明语言服务器并实现启动命令

extension.toml中加入语言服务器条目,写明服务器名称及其适用的语言。languages列表中的条目必须与该语言config.toml里的name字段完全一致:

[language_servers.my-language-server] name = "My Language LSP" languages = ["My Language"]

然后在扩展的 Rust 代码中实现Extensiontrait 的language_server_command方法:

impl zed::Extension for MyExtension { fn language_server_command( &mut self, language_server_id: &LanguageServerId, worktree: &zed::Worktree, ) -> Result<zed::Command> { Ok(zed::Command { command: get_path_to_language_server_executable()?, args: get_args_for_language_server()?, env: get_env_for_language_server()?, }) } }

返回的zed::Commandcommand(可执行文件路径)、args(参数)与env(环境变量)组成。本仓库 Test Extension 源码 给出了贴合实际的实现:先按平台选择二进制路径并下载安装语言服务器,再通过language_server_command返回带args: vec!["lsp".to_string()]的启动命令,并在 language_servers 声明 中对应注册。其 GLSL 扩展 的language_servers声明则展示了languages数组的写法。

你还可以用Extensiontrait 上的多个可选方法自定义对语言服务器的处理,例如用label_for_completion定制补全项的样式(Test Extension 中即通过该方法把 Gleam 的类型签名渲染成 "let a: …" 风格的补全标签)。完整方法列表见 Zed 扩展 API 文档(docs.rs 的 zed_extension_api)。

基于语义 Token 的语法高亮(Semantic Tokens)

Zed 支持使用语言服务器上报的语义 Token 进行语法高亮。该特性默认关闭,可在设置文件中启用:

{ // 全局启用语义 Token,并叠加 tree-sitter 高亮 "semantic_tokens": "combined", // 或者按语言单独指定: "languages": { "Rust": { // 不使用 tree-sitter,只用 LSP 语义 Token: "semantic_tokens": "full" } } }

semantic_tokens设置取值:

  • "off"(默认):不向语言服务器请求语义 Token;
  • "combined":将 LSP 语义 Token 与 tree-sitter 高亮叠加使用;
  • "full":仅使用 LSP 语义 Token,取代 tree-sitter 高亮。
扩展自带的语义 Token 规则

语言扩展可为自家语言服务器上报的自定义 Token 类型提供默认的语义 Token 规则。做法是在语言目录(与config.toml同级)放置semantic_token_rules.json

my-extension/ languages/ my-language/ config.toml highlights.scm semantic_token_rules.json

文件采用与用户设置中semantic_token_rules数组相同的 JSON 格式——一个规则对象数组:

[ { "token_type": "lifetime", "style": ["lifetime"] }, { "token_type": "builtinType", "style": ["type"] }, { "token_type": "selfKeyword", "style": ["variable.special"] } ]

当语言服务器上报自定义的(非标准)Token 类型、而 Zed 内置默认规则未覆盖时,这套机制尤其有用。扩展提供的规则作为该语言的合理默认值——用户永远可以在自己的设置中通过semantic_token_rules覆盖它们;只有用户与扩展规则都不匹配时,才会使用内置默认规则(内置默认规则文件见 assets/settings/default_semantic_token_rules.json)。

定制语义 Token 样式

可以在设置文件中定义规则,定制语义 Token 到主题样式的映射:

{ "global_lsp_settings": { "semantic_token_rules": [ { // 把宏高亮成关键字。 "token_type": "macro", "style": ["syntax.keyword"] }, { // 把未解析引用高亮为加粗红色。 "token_type": "unresolvedReference", "foreground_color": "#c93f3f", "font_weight": "bold" }, { // 为所有可变变量/引用等加下划线。 "token_modifiers": ["mutable"], "underline": true } ] } }

凡是匹配给定token_typetoken_modifiers的规则都会被应用,靠前的规则优先。若没有任何规则匹配,则该 Token 不高亮。规则按如下优先级生效(从高到低):

  1. 用户设置——settings 文件中semantic_token_rules的规则;
  2. 扩展规则——扩展语言目录中semantic_token_rules.json的规则;
  3. 默认规则——Zed 针对标准 LSP Token 类型内置的规则。

semantic_token_rules数组中每条规则的字段定义如下:

  • token_type:LSP 规范定义的语义 Token 类型;省略时匹配所有类型。
  • token_modifiers:要匹配的语义 Token 修饰符列表;须全部命中才算匹配。
  • style:取自当前语法主题的样式列表;取第一个能找到的样式,其后的设置项会覆盖该样式。
  • foreground_color:该类型使用的前景色,十六进制格式(如"#ff0000")。
  • background_color:使用的背景色,十六进制格式(如"#ff0000")。
  • underline:布尔值或十六进制颜色;为true时用文本颜色加下划线。
  • strikethrough:布尔值或十六进制颜色;为true时用文本颜色加删除线。
  • font_weight:取"normal""bold"
  • font_style:取"normal""italic"

多语言支持:language_ids映射

如果语言服务器支持多种语言,可用language_ids将 Zed 语言映射到 LSP 规范期望的languageId

[language-servers.my-language-server] name = "Whatever LSP" languages = ["JavaScript", "HTML", "CSS"] [language-servers.my-language-server.language_ids] "JavaScript" = "javascript" "TSX" = "typescriptreact" "HTML" = "html" "CSS" = "css"

仓库内 HTML 扩展的 extension.toml 即真实采用了这种写法:声明vscode-html-language-server,并在language_ids中把HTML映射为htmlCSS映射为css

小结

从一份config.toml到一整套.scm查询,再到extension.toml中 Grammar 与 LSP 的注册,Zed 把“语言支持”拆成了清晰、可复用的模块。编写扩展时建议:先用 HTML 扩展 与 GLSL 扩展 作为最小可行模板,逐步补齐高亮、缩进、大纲与注入;接入 LSP 后按需定制语义 Token 样式。若要参考更多内置语言的做法,本仓库的 crates/languages/src 收录了 Zed 各内置语言的完整配置与查询,可作为适配各种语言惯用法的直接范本。


  1. 这些注解会被 Assistant 在生成代码修改步骤时使用。

【免费下载链接】zedCode at the speed of thought – Zed is a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter.项目地址: https://gitcode.com/GitHub_Trending/ze/zed

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

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

C++模拟实现二叉搜索树:核心机制与踩坑实录(上)

二叉搜索树这个东西&#xff0c;很多学C的朋友都会遇到。面试高频、算法题常客、STL里 map/set 的底层也有它的影子&#xff0c;但如果只停留在“知道概念”和“刷过几道题”的层面&#xff0c;真让你从零模拟实现一棵可用的二叉搜索树&#xff0c;你会发现一堆平时根本注意不到…

作者头像 李华
网站建设 2026/9/7 23:18:25

Dify + MCP 实战:构建微信端智能理财助手与自动化推送系统

简介&#xff1a;面向金融科技开发者&#xff0c;这份PDF教程完整讲解基于Dify与MCP协议构建智能金融理财助手的全过程&#xff0c;尤其适合有Python基础、希望落地AI智能体与微信自动化推送的工程师。资源共1个PDF文件&#xff0c;压缩包约248KB&#xff0c;内容涵盖核心能力架…

作者头像 李华
网站建设 2026/9/7 23:18:23

单用户模式修改银河麒麟V10密码:完整实操指南

简介&#xff1a;《银河麒麟桌面V10(sp1)用户密码修改指南》是一份面向系统个人用户与运维人员的应急实操手册&#xff0c;专门解决忘记登录密码后无法正常进入系统的问题。内容覆盖X86与ARM双架构&#xff0c;从启动主机进入grub界面讲起&#xff0c;给出在linux行末添加“ini…

作者头像 李华
网站建设 2026/9/7 23:15:41

Obsidian插件生态与效率提升全攻略

1. Obsidian 核心价值与插件生态解析作为一款基于Markdown的本地优先知识管理工具&#xff0c;Obsidian近年来在科研人员、写作者和技术从业者中迅速走红。其核心优势在于将笔记以纯文本形式存储在本地&#xff0c;通过双向链接构建知识网络&#xff0c;同时拥有高度可扩展的插…

作者头像 李华
网站建设 2026/9/7 23:14:53

VS2017与QT插件安装配置全攻略及常见问题解决

1. 项目概述&#xff1a;VS2017与QT插件安装配置痛点解析作为C开发的老兵&#xff0c;我深知Visual Studio 2017与QT插件组合在Windows平台开发中的重要性。这个经典组合却有着令人头疼的安装陷阱——根据我的技术支持记录&#xff0c;超过60%的开发者在首次安装时会遇到各种报…

作者头像 李华
网站建设 2026/9/7 23:11:54

EPLAN杂症:.ema文件导入显示灰色方框?原因与5步修复指南

1. 先说结论&#xff1a;灰色方框到底是怎么来的做电气设计的兄弟&#xff0c;尤其是经常接外部图纸、用别人宏文件的&#xff0c;估计都撞见过这个场景&#xff1a;甲方或者同事发来一个 .ema 文件&#xff0c;说“这是我们标准的设备宏&#xff0c;你直接拖进图里用”。结果你…

作者头像 李华