<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Eric&apos;s Blog</title>
    <description>专注于编程技术、开源项目与生活感悟的独立博客</description>
    <link>https://wsdjeg.net/</link>
    <atom:link href="https://wsdjeg.net/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 08 Apr 2026 04:02:16 +0000</pubDate>
    <lastBuildDate>Wed, 08 Apr 2026 04:02:16 +0000</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      <item>
        <title>GLM-5 流式 Tool Call 异常分析（基于 curl 原始输出）</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#问题背景&quot; id=&quot;markdown-toc-问题背景&quot;&gt;问题背景&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#调用架构与实现&quot; id=&quot;markdown-toc-调用架构与实现&quot;&gt;调用架构与实现&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#客户端请求实现&quot; id=&quot;markdown-toc-客户端请求实现&quot;&gt;客户端请求实现&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#关键请求参数&quot; id=&quot;markdown-toc-关键请求参数&quot;&gt;关键请求参数&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#异常现象详述&quot; id=&quot;markdown-toc-异常现象详述&quot;&gt;异常现象详述&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#正常的-sse-流格式&quot; id=&quot;markdown-toc-正常的-sse-流格式&quot;&gt;正常的 SSE 流格式&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#实际收到的异常数据&quot; id=&quot;markdown-toc-实际收到的异常数据&quot;&gt;实际收到的异常数据&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#异常数据特征分析&quot; id=&quot;markdown-toc-异常数据特征分析&quot;&gt;异常数据特征分析&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#根因分析&quot; id=&quot;markdown-toc-根因分析&quot;&gt;根因分析&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#问题本质协议层混流&quot; id=&quot;markdown-toc-问题本质协议层混流&quot;&gt;问题本质：协议层混流&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#推测的错误实现&quot; id=&quot;markdown-toc-推测的错误实现&quot;&gt;推测的错误实现&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#为什么会出现半截字符串&quot; id=&quot;markdown-toc-为什么会出现半截字符串&quot;&gt;为什么会出现”半截字符串”&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#通道混用的可能原因&quot; id=&quot;markdown-toc-通道混用的可能原因&quot;&gt;通道混用的可能原因&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#对客户端的影响&quot; id=&quot;markdown-toc-对客户端的影响&quot;&gt;对客户端的影响&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#chatnvim-解析器行为&quot; id=&quot;markdown-toc-chatnvim-解析器行为&quot;&gt;chat.nvim 解析器行为&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#实际影响范围&quot; id=&quot;markdown-toc-实际影响范围&quot;&gt;实际影响范围&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#临时容错方案&quot; id=&quot;markdown-toc-临时容错方案&quot;&gt;临时容错方案&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#调试与验证方法&quot; id=&quot;markdown-toc-调试与验证方法&quot;&gt;调试与验证方法&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#保存原始响应&quot; id=&quot;markdown-toc-保存原始响应&quot;&gt;保存原始响应&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#分析响应内容&quot; id=&quot;markdown-toc-分析响应内容&quot;&gt;分析响应内容&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#验证-tool-call-完整性&quot; id=&quot;markdown-toc-验证-tool-call-完整性&quot;&gt;验证 Tool Call 完整性&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#结论与建议&quot; id=&quot;markdown-toc-结论与建议&quot;&gt;结论与建议&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#问题定性&quot; id=&quot;markdown-toc-问题定性&quot;&gt;问题定性&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#根本原因&quot; id=&quot;markdown-toc-根本原因&quot;&gt;根本原因&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#解决建议&quot; id=&quot;markdown-toc-解决建议&quot;&gt;解决建议&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#后续跟进&quot; id=&quot;markdown-toc-后续跟进&quot;&gt;后续跟进&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#参考资料&quot; id=&quot;markdown-toc-参考资料&quot;&gt;参考资料&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;问题背景&quot;&gt;问题背景&lt;/h2&gt;

本文记录在使用 &lt;strong&gt;阿里云百炼平台 Coding Plan（GLM-5 模型）&lt;/strong&gt; 时遇到的一个流式输出协议异常问题。请求客户端为 Neovim 插件 &lt;strong&gt;chat.nvim&lt;/strong&gt;，通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt; 命令异步调用阿里云的流式聊天补全接口。

在正常开发过程中，chat.nvim 需要调用大模型完成代码生成、问题解答等任务，并支持 Tool Call 功能以扩展模型能力。然而在实际使用中，发现当模型返回 Tool Call 响应时，SSE（Server-Sent Events）流中会夹杂未经封装的原始文本数据，导致客户端解析失败。

&lt;hr /&gt;

&lt;h2 id=&quot;调用架构与实现&quot;&gt;调用架构与实现&lt;/h2&gt;

&lt;h3 id=&quot;客户端请求实现&quot;&gt;客户端请求实现&lt;/h3&gt;

chat.nvim 底层使用 Neovim 的 job 系统异步执行 curl 命令，通过标准输入输出与服务端通信。核心请求函数如下：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;curl&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;-s&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;https://coding.dashscope.aliyuncs.com/v1/chat/completions&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;-H&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;Content-Type: application/json&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;-H&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;Authorization: Bearer &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api_key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aliyuncs_pc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;-X&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;POST&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;-d&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;@-&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sessions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_session_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;enable_thinking&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stream_options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;include_usage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tools&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;chat.tools&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;available_tools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jobid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;on_stderr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on_stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;on_exit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jobid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jobid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sessions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_session_jobid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jobid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jobid&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;关键请求参数&quot;&gt;关键请求参数&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;参数&lt;/th&gt;
      &lt;th&gt;配置值&lt;/th&gt;
      &lt;th&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;服务端点&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://coding.dashscope.aliyuncs.com/v1/chat/completions&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;阿里云百炼平台 API&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;模型&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glm-5&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;GLM-5 模型（Coding Plan）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;流式输出&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stream = true&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;启用 SSE 流式响应&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Tool Call&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tools = available_tools()&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;注册可用工具函数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;思考模式&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enable_thinking = true&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;启用模型思考过程&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;使用量统计&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stream_options.include_usage = true&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;返回 token 使用统计&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

请求体通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -d @-&lt;/code&gt; 从标准输入读取，job 系统通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;job.send()&lt;/code&gt; 将 JSON 编码的请求体发送给 curl 进程。响应数据通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_stdout&lt;/code&gt; 回调逐行接收，客户端需要实时解析 SSE 格式的数据流。

&lt;hr /&gt;

&lt;h2 id=&quot;异常现象详述&quot;&gt;异常现象详述&lt;/h2&gt;

&lt;h3 id=&quot;正常的-sse-流格式&quot;&gt;正常的 SSE 流格式&lt;/h3&gt;

符合 OpenAI 规范的 SSE 流式响应应当严格遵循以下格式，每一行都以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data: &lt;/code&gt; 前缀开头，后面跟随完整的 JSON 对象或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[DONE]&lt;/code&gt; 标记：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;data: {&quot;id&quot;:&quot;chat-123&quot;,&quot;choices&quot;:[{&quot;delta&quot;:{&quot;content&quot;:&quot;Hello&quot;},&quot;index&quot;:0}]}
data: {&quot;id&quot;:&quot;chat-123&quot;,&quot;choices&quot;:[{&quot;delta&quot;:{&quot;content&quot;:&quot; world&quot;},&quot;index&quot;:0}]}
data: {&quot;id&quot;:&quot;chat-123&quot;,&quot;choices&quot;:[{&quot;delta&quot;:{&quot;content&quot;:&quot;!&quot;},&quot;index&quot;:0}]}
data: {&quot;id&quot;:&quot;chat-123&quot;,&quot;choices&quot;:[{&quot;finish_reason&quot;:&quot;stop&quot;,&quot;index&quot;:0}]}
data: [DONE]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

客户端解析器通过检测 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data: &lt;/code&gt; 前缀识别有效数据行，使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.json.decode()&lt;/code&gt; 解析 JSON 内容，遇到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[DONE]&lt;/code&gt; 标记时结束流式处理。

&lt;h3 id=&quot;实际收到的异常数据&quot;&gt;实际收到的异常数据&lt;/h3&gt;

在实际调用 GLM-5 模型时，收到的响应流中出现了不符合 SSE 规范的裸文本数据：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;data: {&quot;id&quot;:&quot;chat-456&quot;,&quot;choices&quot;:[{&quot;delta&quot;:{&quot;content&quot;:&quot;请查看&quot;},&quot;index&quot;:0}]}
data: {&quot;id&quot;:&quot;chat-456&quot;,&quot;choices&quot;:[{&quot;delta&quot;:{&quot;tool_calls&quot;:[{&quot;id&quot;:&quot;call_1&quot;,&quot;function&quot;:{&quot;name&quot;:&quot;read_file&quot;,&quot;arguments&quot;:&quot;&quot;},&quot;index&quot;:0}]}]}
ts from you under
this License for any purpose whatsoever, with or without
data: {&quot;id&quot;:&quot;chat-456&quot;,&quot;choices&quot;:[{&quot;delta&quot;:{&quot;tool_calls&quot;:[{&quot;function&quot;:{&quot;arguments&quot;:&quot;\&quot;--filepath\&quot;&quot;},&quot;index&quot;:0}]}]}
data: {&quot;id&quot;:&quot;chat-456&quot;,&quot;choices&quot;:[{&quot;finish_reason&quot;:&quot;tool_calls&quot;,&quot;index&quot;:0}]}
data: [DONE]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

可以看到在第 2 行和第 3 行之间，插入了两行没有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data: &lt;/code&gt; 前缀的纯文本内容。这些文本实际上是 Tool Call 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arguments&lt;/code&gt; 参数值的一部分，应该是 GPL 许可证文本的片段。

&lt;h3 id=&quot;异常数据特征分析&quot;&gt;异常数据特征分析&lt;/h3&gt;

通过对多次请求的原始响应进行比对，总结出以下异常特征：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;特征&lt;/th&gt;
      &lt;th&gt;表现&lt;/th&gt;
      &lt;th&gt;出现频率&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;裸文本行&lt;/td&gt;
      &lt;td&gt;无 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data: &lt;/code&gt; 前缀的纯文本&lt;/td&gt;
      &lt;td&gt;每次 Tool Call 必现&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;内容来源&lt;/td&gt;
      &lt;td&gt;Tool Call arguments 字符串片段&lt;/td&gt;
      &lt;td&gt;100%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;出现位置&lt;/td&gt;
      &lt;td&gt;tool_calls delta 输出过程中&lt;/td&gt;
      &lt;td&gt;100%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;content 输出&lt;/td&gt;
      &lt;td&gt;正常 SSE 格式&lt;/td&gt;
      &lt;td&gt;不受影响&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;finish_reason&lt;/td&gt;
      &lt;td&gt;正确返回 tool_calls&lt;/td&gt;
      &lt;td&gt;不受影响&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;JSON 完整性&lt;/td&gt;
      &lt;td&gt;tool_call JSON 被截断&lt;/td&gt;
      &lt;td&gt;100%&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

这些特征表明问题具有高度一致性，并非网络传输错误或偶发异常，而是服务端实现层面的系统性问题。

&lt;hr /&gt;

&lt;h2 id=&quot;根因分析&quot;&gt;根因分析&lt;/h2&gt;

&lt;h3 id=&quot;问题本质协议层混流&quot;&gt;问题本质：协议层混流&lt;/h3&gt;

该问题的本质是服务端在流式输出过程中，存在两条独立的输出通道被错误地混合写入同一个 HTTP 响应流：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;输出类型&lt;/th&gt;
      &lt;th&gt;预期通道&lt;/th&gt;
      &lt;th&gt;实际通道&lt;/th&gt;
      &lt;th&gt;状态&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;普通内容 (content)&lt;/td&gt;
      &lt;td&gt;SSE JSON 封装&lt;/td&gt;
      &lt;td&gt;SSE JSON 封装&lt;/td&gt;
      &lt;td&gt;✅ 正常&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tool Call 参数 (arguments)&lt;/td&gt;
      &lt;td&gt;SSE JSON 封装&lt;/td&gt;
      &lt;td&gt;原始 stdout 直写&lt;/td&gt;
      &lt;td&gt;❌ 异常&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

正常情况下，所有输出内容都应当经过 SSE 协议封装层，统一格式化为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data: {...}&lt;/code&gt; 后写入 HTTP 响应体。但实际实现中，Tool Call 的 arguments 生成逻辑绕过了封装层，直接将 token 写入输出流。

&lt;h3 id=&quot;推测的错误实现&quot;&gt;推测的错误实现&lt;/h3&gt;

根据输出特征，推测服务端可能存在类似以下的错误实现：

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;// ❌ 错误实现示意&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;streamToolCallArguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokens&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ResponseWriter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;range&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokens&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;// 错误：直接写入原始 token，未经过 SSE 封装&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Flusher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Flush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;// ✅ 正确实现应当是&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;streamToolCallArguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokens&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ResponseWriter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;range&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokens&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;// 正确：构造完整的 SSE 消息&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SSEMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Choices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Choice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;Delta&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Delta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;ToolCalls&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToolCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;n&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                                    &lt;span class=&quot;n&quot;&gt;Arguments&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                            &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Fprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Marshal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Flusher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Flush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;为什么会出现半截字符串&quot;&gt;为什么会出现”半截字符串”&lt;/h3&gt;

观察到的裸文本如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ts from you under&lt;/code&gt; 实际上是 arguments 字符串的中间片段。这是因为：

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Token 级流式输出&lt;/strong&gt;：模型生成 arguments 时按 token 逐个输出，而非等待完整字符串生成后一次性输出&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;写入时机错误&lt;/strong&gt;：每个 token 生成后立即被写入输出流，但未经过 JSON 转义和 SSE 封装&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;边界不匹配&lt;/strong&gt;：token 切分点与 JSON 字符串边界不一致，导致输出的是字符串中间片段&lt;/li&gt;
&lt;/ol&gt;

例如，当 arguments 应该是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;GPL License text from you under this License&quot;&lt;/code&gt; 时，实际输出可能是：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;data: {&quot;arguments&quot;:&quot;GPL Licen&quot;}   // 正常 SSE
se text from you under            // 裸文本（错误）
this License&quot;                     // 裸文本（错误）
data: {&quot;arguments&quot;:&quot;&quot;}            // 正常 SSE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;通道混用的可能原因&quot;&gt;通道混用的可能原因&lt;/h3&gt;

从软件工程角度分析，这种问题通常由以下原因导致：

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;代码路径分支&lt;/strong&gt;：content 输出和 tool_call 输出走了不同的代码路径，其中一条路径遗漏了封装逻辑&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;历史遗留代码&lt;/strong&gt;：可能在迭代过程中，tool_call 功能是后期添加的，复用了旧的输出接口&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;测试覆盖不足&lt;/strong&gt;：缺少对原始 HTTP 响应流的协议一致性测试，仅测试了最终解析结果&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;多团队协作&lt;/strong&gt;：流式输出模块和 Tool Call 模块可能由不同团队开发，接口约定不清晰&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;对客户端的影响&quot;&gt;对客户端的影响&lt;/h2&gt;

&lt;h3 id=&quot;chatnvim-解析器行为&quot;&gt;chat.nvim 解析器行为&lt;/h3&gt;

chat.nvim 的 SSE 解析器期望每一行输入都是合法的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data: {...}&lt;/code&gt; 格式，当遇到裸文本时会出现以下问题：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 简化的解析逻辑&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_sse_line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;-- 去掉 &quot;data: &quot; 前缀&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;-- 裸文本会导致这里报错&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当输入行为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ts from you under&lt;/code&gt; 时：

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;line:sub(7)&lt;/code&gt; 返回 ` from you under`（或原样返回，如果行长度不足 7）&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.json.decode()&lt;/code&gt; 尝试解析非 JSON 字符串，抛出异常&lt;/li&gt;
  &lt;li&gt;异常可能导致整个流式处理中断，Tool Call 无法完成&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;实际影响范围&quot;&gt;实际影响范围&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;影响项&lt;/th&gt;
      &lt;th&gt;严重程度&lt;/th&gt;
      &lt;th&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;JSON 解析失败&lt;/td&gt;
      &lt;td&gt;高&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.json.decode()&lt;/code&gt; 抛出异常&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tool Call 识别失败&lt;/td&gt;
      &lt;td&gt;高&lt;/td&gt;
      &lt;td&gt;arguments 内容不完整，无法调用工具&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;流式输出中断&lt;/td&gt;
      &lt;td&gt;中&lt;/td&gt;
      &lt;td&gt;可能触发错误处理逻辑，提前终止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;用户体验下降&lt;/td&gt;
      &lt;td&gt;中&lt;/td&gt;
      &lt;td&gt;功能不可用或响应异常&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;错误日志污染&lt;/td&gt;
      &lt;td&gt;低&lt;/td&gt;
      &lt;td&gt;产生大量解析错误日志&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;临时容错方案&quot;&gt;临时容错方案&lt;/h3&gt;

在无法修改服务端的情况下，客户端可以增加容错逻辑，过滤非法数据行：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;safe_parse_sse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;-- 严格过滤：只处理以 &quot;data: &quot; 开头的行&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^data: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;跳过非法 SSE 行：&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pcall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;[DONE]&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DONE&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;JSON 解析失败：&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 在 on_stdout 回调中使用&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gmatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;[^&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;]+&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parsed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;safe_parse_sse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parsed&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;handle_chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

该方案的核心思想是&lt;strong&gt;严格过滤 + 静默丢弃&lt;/strong&gt;，遇到非法数据行时记录警告日志但不中断处理流程。这样可以保证在服务端修复问题之前，客户端仍能正常工作。

&lt;hr /&gt;

&lt;h2 id=&quot;调试与验证方法&quot;&gt;调试与验证方法&lt;/h2&gt;

&lt;h3 id=&quot;保存原始响应&quot;&gt;保存原始响应&lt;/h3&gt;

使用 curl 直接请求并保存完整响应，便于离线分析：

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl &lt;span class=&quot;nt&quot;&gt;-N&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  https://coding.dashscope.aliyuncs.com/v1/chat/completions &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type: application/json&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Authorization: Bearer YOUR_API_KEY&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{
    &quot;model&quot;: &quot;glm-5&quot;,
    &quot;messages&quot;: [
      {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;请读取当前目录下的 LICENSE 文件&quot;}
    ],
    &quot;stream&quot;: true,
    &quot;tools&quot;: [
      {
        &quot;type&quot;: &quot;function&quot;,
        &quot;function&quot;: {
          &quot;name&quot;: &quot;read_file&quot;,
          &quot;parameters&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;properties&quot;: {
              &quot;filepath&quot;: {&quot;type&quot;: &quot;string&quot;}
            }
          }
        }
      }
    ]
  }&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; raw_response.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

参数说明：
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-N&lt;/code&gt;：禁用缓冲，实时输出&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw_response.txt&lt;/code&gt;：保存完整原始响应&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;分析响应内容&quot;&gt;分析响应内容&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 统计总行数&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;wc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; raw_response.txt

&lt;span class=&quot;c&quot;&gt;# 查看非 data: 开头的行（非法行）&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;^data: &quot;&lt;/span&gt; raw_response.txt

&lt;span class=&quot;c&quot;&gt;# 统计非法行数量&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-cv&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;^data: &quot;&lt;/span&gt; raw_response.txt

&lt;span class=&quot;c&quot;&gt;# 查看非法行的上下文（前后各 2 行）&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;^data: &quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-B&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; 2 raw_response.txt

&lt;span class=&quot;c&quot;&gt;# 提取所有 data: 行并验证 JSON 格式&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;^data: &quot;&lt;/span&gt; raw_response.txt | &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/^data: //&apos;&lt;/span&gt; | &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read &lt;/span&gt;line&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; | jq &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; 2&amp;gt;/dev/null &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;INVALID: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;验证-tool-call-完整性&quot;&gt;验证 Tool Call 完整性&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 提取所有 tool_calls 相关的行&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;tool_calls&quot;&lt;/span&gt; raw_response.txt

&lt;span class=&quot;c&quot;&gt;# 检查 arguments 字段是否完整&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;arguments&quot;&lt;/span&gt; raw_response.txt | &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/^data: //&apos;&lt;/span&gt; | &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  jq &lt;span class=&quot;s1&quot;&gt;&apos;.choices[0].delta.tool_calls[0].function.arguments&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果 arguments 字段显示不完整或解析失败，说明存在数据污染。

&lt;hr /&gt;

&lt;h2 id=&quot;结论与建议&quot;&gt;结论与建议&lt;/h2&gt;

&lt;h3 id=&quot;问题定性&quot;&gt;问题定性&lt;/h3&gt;

该问题属于&lt;strong&gt;服务端协议层实现缺陷&lt;/strong&gt;，具体表现为：

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;非客户端问题&lt;/strong&gt;：chat.nvim 的 SSE 解析逻辑符合 OpenAI 规范&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;非网络问题&lt;/strong&gt;：裸文本稳定出现，非传输错误&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;非偶发问题&lt;/strong&gt;：每次 Tool Call 必现，具有可复现性&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;协议级错误&lt;/strong&gt;：违反 SSE 协议规范，混合输出不同格式数据&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;根本原因&quot;&gt;根本原因&lt;/h3&gt;

Tool Call 的 arguments 在流式生成过程中未被正确封装进 SSE 消息格式，导致原始 token 直接泄漏到 HTTP 响应流中。这反映了服务端在流式输出模块和 Tool Call 模块的集成测试不足。

&lt;h3 id=&quot;解决建议&quot;&gt;解决建议&lt;/h3&gt;

&lt;strong&gt;对服务端（阿里云）&lt;/strong&gt;：

&lt;ol&gt;
  &lt;li&gt;修复 arguments 输出路径，确保所有输出经过 SSE 封装层&lt;/li&gt;
  &lt;li&gt;增加协议一致性测试，验证响应流符合 SSE 规范&lt;/li&gt;
  &lt;li&gt;提供问题追踪和修复时间表&lt;/li&gt;
&lt;/ol&gt;

&lt;strong&gt;对客户端（chat.nvim）&lt;/strong&gt;：

&lt;ol&gt;
  &lt;li&gt;增加 SSE 行过滤逻辑，容忍非法数据&lt;/li&gt;
  &lt;li&gt;记录详细的解析错误日志，便于问题诊断&lt;/li&gt;
  &lt;li&gt;考虑增加协议一致性检查，主动检测服务端问题&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;后续跟进&quot;&gt;后续跟进&lt;/h3&gt;

建议将原始响应日志提交给阿里云技术支持，附上：
&lt;ul&gt;
  &lt;li&gt;完整的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw_response.txt&lt;/code&gt; 文件&lt;/li&gt;
  &lt;li&gt;请求参数和调用时间&lt;/li&gt;
  &lt;li&gt;问题复现步骤&lt;/li&gt;
  &lt;li&gt;期望的正确输出格式&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;参考资料&quot;&gt;参考资料&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.aliyun.com/zh/model-studio/developer-reference/chat-completion-api&quot;&gt;阿里云百炼平台 API 文档&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://platform.openai.com/docs/api-reference/chat/create&quot;&gt;OpenAI Chat Completion API&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://html.spec.whatwg.org/multipage/server-sent-events.html&quot;&gt;Server-Sent Events 规范&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events&quot;&gt;MDN: Using Server-Sent Events&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/chat-nvim/chat.nvim&quot;&gt;chat.nvim 项目源码&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Sat, 21 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/glm5-streaming-toolcall-analysis/</link>
        <guid isPermaLink="true">https://wsdjeg.net/glm5-streaming-toolcall-analysis/</guid>
        
        <category>SSE</category>
        
        <category>Tool Call</category>
        
        <category>GLM</category>
        
        <category>流式输出</category>
        
        <category>阿里云</category>
        
        
        <category>技术分析</category>
        
      </item>
    
      <item>
        <title>job.nvim raw 参数导致 JSON 解析失败</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#问题复现&quot; id=&quot;markdown-toc-问题复现&quot;&gt;问题复现&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#问题分析&quot; id=&quot;markdown-toc-问题分析&quot;&gt;问题分析&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#对比两种模式&quot; id=&quot;markdown-toc-对比两种模式&quot;&gt;对比两种模式&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#默认模式raw--false&quot; id=&quot;markdown-toc-默认模式raw--false&quot;&gt;默认模式（raw = false）&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#raw-模式raw--true&quot; id=&quot;markdown-toc-raw-模式raw--true&quot;&gt;Raw 模式（raw = true）&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#解决方案&quot; id=&quot;markdown-toc-解决方案&quot;&gt;解决方案&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#方案一使用-raw-模式并手动拼接数据&quot; id=&quot;markdown-toc-方案一使用-raw-模式并手动拼接数据&quot;&gt;方案一：使用 raw 模式并手动拼接数据&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#方案二在默认模式下正确处理数据&quot; id=&quot;markdown-toc-方案二在默认模式下正确处理数据&quot;&gt;方案二：在默认模式下正确处理数据&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#方案三使用-luv-的-stream-api&quot; id=&quot;markdown-toc-方案三使用-luv-的-stream-api&quot;&gt;方案三：使用 luv 的 stream API&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#实际案例&quot; id=&quot;markdown-toc-实际案例&quot;&gt;实际案例&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#总结&quot; id=&quot;markdown-toc-总结&quot;&gt;总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

最近在使用 job.nvim 执行一些命令时，遇到了一个奇怪的问题。当我执行一个返回 JSON 数据的命令时，发现 JSON 数据无法被正确解析，总是报错 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unexpected end of JSON&lt;/code&gt;。经过调试后发现，问题出在 job.nvim 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw&lt;/code&gt; 参数默认值上。

&lt;h2 id=&quot;问题复现&quot;&gt;问题复现&lt;/h2&gt;

假设我们有一个命令，它会输出一个较大的 JSON 数据：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;job&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jobid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;some-command-that-outputs-json&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on_exit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;table.concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoded&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pcall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;JSON decode failed: &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;JSON decoded successfully&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decoded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行上述代码后，可能会看到类似以下的错误：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;JSON decode failed: Expected object key string but found null at character 1024
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

或者在解析时直接报错：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;JSON decode failed: Expected value but found T_END at character 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;问题分析&quot;&gt;问题分析&lt;/h2&gt;

要理解这个问题，需要先了解 job.nvim 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw&lt;/code&gt; 参数的作用。查看 job.nvim 的源码，可以看到：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;--- @class JobOpts&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;--- @field on_stderr? function&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;--- @field on_exit? fun(id: integer, code: integer, signin: integer)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;--- @field on_stdout? function&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;--- @field cwd? string&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;--- @field detached? boolean&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;--- @field clear_env? boolean&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;--- @field env? table&amp;lt;string, string|number&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;--- @field encoding? string&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;--- @field raw? boolean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw&lt;/code&gt; 参数默认是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;（即 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;），这意味着使用&lt;strong&gt;行缓冲模式&lt;/strong&gt;。在这种模式下，数据会通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffered_data&lt;/code&gt; 函数处理：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;---@param eof string&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;---@param data string&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;buffered_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eof&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;eof&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;table.remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eof&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eof&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;eof&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eof&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;eof&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std_data&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这个函数的逻辑是：

&lt;ol&gt;
  &lt;li&gt;将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\r\n&lt;/code&gt; 替换为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\n&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;按换行符 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\n&lt;/code&gt; 分割数据&lt;/li&gt;
  &lt;li&gt;处理不完整的行，保存到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eof&lt;/code&gt; 变量中等待下一次数据&lt;/li&gt;
&lt;/ol&gt;

问题在于：&lt;strong&gt;大多数 JSON 输出是不包含换行符的单行数据&lt;/strong&gt;，或者是一个格式化的多行 JSON。当 JSON 数据较大时，可能会被系统分成多个数据块（chunk），但每个数据块内部可能没有换行符。

在这种情况下，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffered_data&lt;/code&gt; 函数会：

&lt;ol&gt;
  &lt;li&gt;如果数据块中没有换行符，会将整个数据块视为一个”不完整的行”，保存到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eof&lt;/code&gt; 中&lt;/li&gt;
  &lt;li&gt;此时 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std_data&lt;/code&gt; 是空的，不会触发 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_stdout&lt;/code&gt; 回调&lt;/li&gt;
  &lt;li&gt;只有当下一个数据块到来或者 EOF 时，才会将之前保存的数据输出&lt;/li&gt;
&lt;/ol&gt;

这样就导致了数据在缓冲区中累积，但 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_stdout&lt;/code&gt; 回调可能不会及时接收到数据。更糟糕的是，如果 JSON 数据本身就包含换行符（格式化的 JSON），会被错误地分割成多行。

&lt;h2 id=&quot;对比两种模式&quot;&gt;对比两种模式&lt;/h2&gt;

&lt;h3 id=&quot;默认模式raw--false&quot;&gt;默认模式（raw = false）&lt;/h3&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- Default: line-buffered mode&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;uv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout_data&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_jobs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;jobid_&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout_eof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;buffered_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_jobs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;jobid_&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout_eof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;stdout_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tbl_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iconv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;utf-8&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;-- ... EOF handling&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;raw-模式raw--true&quot;&gt;Raw 模式（raw = true）&lt;/h3&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- Raw mode: no buffering, pass raw data chunks directly&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;uv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iconv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;utf-8&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nparams&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;stdout&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;-- EOF&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_closing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

可以看到，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw = true&lt;/code&gt; 模式下：

&lt;ol&gt;
  &lt;li&gt;不进行行缓冲处理&lt;/li&gt;
  &lt;li&gt;直接将原始数据块传递给回调函数&lt;/li&gt;
  &lt;li&gt;数据可能会被分成多个块，每个块都是不完整的&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;解决方案&quot;&gt;解决方案&lt;/h2&gt;

针对 JSON 数据解析的场景，有以下几种解决方案：

&lt;h3 id=&quot;方案一使用-raw-模式并手动拼接数据&quot;&gt;方案一：使用 raw 模式并手动拼接数据&lt;/h3&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;job&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jobid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;some-command-that-outputs-json&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;-- 使用原始模式&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- data 是一个包含原始数据块的列表&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on_exit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;table.concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoded&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pcall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;JSON decode failed: &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;JSON decoded successfully&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decoded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;方案二在默认模式下正确处理数据&quot;&gt;方案二：在默认模式下正确处理数据&lt;/h3&gt;

如果 JSON 数据是单行输出（minified JSON），需要在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_exit&lt;/code&gt; 回调中处理缓冲区中剩余的数据：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;job&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jobid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;some-command-that-outputs-json&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;-- 如果 JSON 是格式化的多行，需要保留换行符&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on_exit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- 拼接所有行，如果是 minified JSON，不需要换行符&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- 如果是格式化 JSON，需要添加换行符&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;table.concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoded&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pcall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;JSON decode failed: &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;JSON decoded successfully&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decoded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;方案三使用-luv-的-stream-api&quot;&gt;方案三：使用 luv 的 stream API&lt;/h3&gt;

如果需要更精细的控制，可以直接使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.loop&lt;/code&gt; (或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.uv&lt;/code&gt;) 的 stream API：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uv&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loop&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;some-command&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;stdio&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;table.concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoded&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pcall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;JSON decode failed: &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;JSON decoded successfully&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decoded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;uv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;实际案例&quot;&gt;实际案例&lt;/h2&gt;

在我开发的 &lt;a href=&quot;https://github.com/wsdjeg/chat.nvim&quot;&gt;chat.nvim&lt;/a&gt; 插件中，调用 AI API 时返回的就是 JSON 数据。最初使用默认模式时，遇到了数据解析失败的问题。

查看调试日志：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ 14:23:42:123 ] [ Info  ] Received chunk 1: {&quot;id&quot;:&quot;chatcmpl-123&quot;,&quot;object&quot;:&quot;chat.completion&quot;,&quot;created&quot;:1234567890
[ 14:23:42:125 ] [ Info  ] Received chunk 2: ,&quot;model&quot;:&quot;gpt-4&quot;,&quot;choices&quot;:[{&quot;index&quot;:0,&quot;message&quot;:{&quot;role&quot;:&quot;assistant&quot;
[ 14:23:42:127 ] [ Info  ] Received chunk 3: ,&quot;content&quot;:&quot;Hello&quot;},&quot;finish_reason&quot;:&quot;stop&quot;}]}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

可以看到，JSON 数据被分成了 3 个数据块，每个块都不完整。在默认模式下，这些数据会被缓冲，等待换行符，但 JSON 数据中没有换行符，导致数据一直在缓冲区中。

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw = true&lt;/code&gt; 后，可以正确地接收并拼接这些数据块：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;job&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chunks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chunks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on_exit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json_str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;table.concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chunks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- 现在可以正确解析 JSON&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- 处理响应数据&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

job.nvim 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw&lt;/code&gt; 参数默认为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;，使用行缓冲模式，适合处理以行为单位的文本输出（如日志、命令输出等）。但如果要处理二进制数据或单行的大型 JSON 数据，应该设置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw = true&lt;/code&gt;，然后在回调函数中手动拼接数据块。

理解 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw&lt;/code&gt; 参数的作用对于正确处理外部命令的输出非常重要：

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;raw = false（默认）&lt;/strong&gt;：行缓冲模式，按换行符分割数据，确保每次回调传递完整的行&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;raw = true&lt;/strong&gt;：原始模式，直接传递数据块，适合处理二进制数据或需要手动拼接的场景&lt;/li&gt;
&lt;/ul&gt;

在使用 job.nvim 处理 JSON 数据时，建议使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw = true&lt;/code&gt; 并在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_exit&lt;/code&gt; 回调中拼接所有数据块后再进行解析。
</description>
        <pubDate>Tue, 10 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/job-nvim-raw-json-parsing/</link>
        <guid isPermaLink="true">https://wsdjeg.net/job-nvim-raw-json-parsing/</guid>
        
        <category>neovim</category>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>为什么仍然在使用 job.nvim</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#使用-lua-重写-job-api&quot; id=&quot;markdown-toc-使用-lua-重写-job-api&quot;&gt;使用 Lua 重写 job API&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#独立成-jobnvim&quot; id=&quot;markdown-toc-独立成-jobnvim&quot;&gt;独立成 job.nvim&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#为什么不切换到-vimsystem&quot; id=&quot;markdown-toc-为什么不切换到-vimsystem&quot;&gt;为什么不切换到 vim.system&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#写在最后&quot; id=&quot;markdown-toc-写在最后&quot;&gt;写在最后&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

job.nvim 发布了 1.5 版本，和往常一样，我在 Reddit 上发布了版本更新文章，也很感谢有不少正面的反馈。

但让我无法理解的是，有些人似乎很难沟通，他们一再强调 Neovim 有内置的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jobstart()&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.system()&lt;/code&gt;，为什么还要创建一个新的插件？即使解释了原因，他们仍然无法理解。我想这可能是我说得不够清楚，因此在这里整理一下前因后果。

说起 Job 函数，要从最早期的 Neovim 版本说起。Neovim 增加了一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jobstart()&lt;/code&gt; Vim Script 函数，那时候 Vim 还没有 Job 功能，后来 Vim 才增加了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;job_start()&lt;/code&gt; 函数，但其调用方式与 Neovim 并不一致。早期的 Neovim 主要还是以使用 VimL 为主。

于是我给 SpaceVim 添加了一个 Job API，以兼容早期 Neovim 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jobstart()&lt;/code&gt; 和 Vim 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;job_start()&lt;/code&gt; 函数。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;commit 44ad1cb4fe6a8d9ccae49b71994e6182bbcaa968
Author: wsdjeg &amp;lt;wsdjeg@163.com&amp;gt;
Date:   Fri Mar 31 21:09:38 2017 +0800

    Add job api for vim and neovim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这样，就可以使用相同的函数同时兼容 Vim 和 Neovim。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:JOB&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; SpaceVim#api#&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;job&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;echo&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;hello world&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; event&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;&quot; data 是一个字符串列表&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:data&lt;/span&gt;
        echo &lt;span class=&quot;nb&quot;&gt;line&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:JOB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s:command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;on_stdout&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;s:stdout&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在这个过程中，前后还遇到过很多兼容性问题。Neovim 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jobstart()&lt;/code&gt; 函数的 stdout callback 在数据过大时会被截断，具体的 buffer size 我记不清了，有个 issue 讨论过这个问题。于是，我在这个 API 中增加了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data_eol&lt;/code&gt; 检测，以确保 callback 函数被调用时传入的是完整的数据。当然，后来的 Neovim 官方文档里也写了如何处理这种数据被截断的情况，详见 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h channel_buffered&lt;/code&gt;。

&lt;h2 id=&quot;使用-lua-重写-job-api&quot;&gt;使用 Lua 重写 job API&lt;/h2&gt;

随着 Neovim 对 Lua 的支持越来越多，我后来&lt;a href=&quot;https://github.com/wsdjeg/SpaceVim/pull/4893&quot;&gt;使用 Lua 重写了 Job API&lt;/a&gt;，但仍然将其内置在 SpaceVim 里。重写之后，调用就可以直接使用 Lua 了。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;commit 879129388ab22b64c5a5cf0df83799084cab96fc
Author: Eric Wong &amp;lt;wsdjeg@outlook.com&amp;gt;
Date:   Wed Jul 5 22:58:01 2023 +0800

    feat(api): add lua job api
    
    close https://github.com/neovim/neovim/issues/20856
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

调用方式变成了 Lua：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;spacevim.api.job&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jobid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test_ctags_cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on_stderr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on_exit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;exit code&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;exit signal&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;独立成-jobnvim&quot;&gt;独立成 job.nvim&lt;/h2&gt;

随着 SpaceVim 项目停止维护，我把我常用的功能插件独立成了&lt;a href=&quot;../why-spacevim-is-archived/#%E6%8F%92%E4%BB%B6%E5%88%97%E8%A1%A8&quot;&gt;各个单独的 Neovim 插件&lt;/a&gt;，其中就包括了 &lt;a href=&quot;https://github.com/wsdjeg/job.nvim&quot;&gt;job.nvim&lt;/a&gt;。

我自己写的很多需要异步执行命令的 Neovim 插件都依赖这个 job.nvim，这样就不需要在每个插件仓库里单独维护执行外部命令的模块了。使用起来也比原来的 SpaceVim 内置 Lua Job API 更简洁一些：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;job&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;on_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;job &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos; exit code:&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos; signal:&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;echo&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;hello world&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jobid1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;on_exit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;on_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;jobid is %s&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jobid1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jobid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;cat&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;on_exit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;job &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos; exit code:&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos; signal:&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jobid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;hello&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chanclose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jobid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;stdin&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;为什么不切换到-vimsystem&quot;&gt;为什么不切换到 vim.system&lt;/h2&gt;

我不太记得 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.system&lt;/code&gt; 是什么时候加入到 Neovim 的了，其前后应该也功能迭代过几个版本。为什么我还在继续维护 job.nvim 而不切换到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.system&lt;/code&gt; 呢？

&lt;ol&gt;
  &lt;li&gt;
    没有对 stdout 数据进行拼接处理，容易有截断数据，而且传给 callback 函数的数据是 string 而非像 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jobstart&lt;/code&gt; 那样是 string 列表。当然，数据类型都是次要的事情，使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;split&lt;/code&gt; 函数很容易得到列表，但是未做数据拼接这点，在写 callback 函数时会增加很多额外的代码量。
  &lt;/li&gt;
  &lt;li&gt;
    callback 函数内无法确认到底是哪个 job 调用触发的这个 callback 函数，应该像 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jobstart()&lt;/code&gt; 的 stdout callback 函数那样，传入一个 jobid 参数。
  &lt;/li&gt;
&lt;/ol&gt;

我创建 job.nvim 的主要原因是：

在旧的 Neovim 版本中，没有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.system&lt;/code&gt;。第一个版本是 job.vim，它使用 VimL，并以与 Neovim 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jobstart&lt;/code&gt; 相同的 API 支持 Neovim 和 Vim。

我需要为不同的 job 的 stdout 使用相同的 callback 函数。例如，在我的插件管理器 &lt;a href=&quot;https://github.com/wsdjeg/nvim-plug&quot;&gt;https://github.com/wsdjeg/nvim-plug&lt;/a&gt; 中，当同时克隆 8 个插件时，我需要在 job 退出前显示每个 job 的进度。因此在 stdout callback 函数中，我需要知道是哪个 job 触发了这个 callback 函数。据我所知，即使现在的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.system&lt;/code&gt; 的 stdout callback 也不支持这个功能。

两种写法，哪种更简单方便，一目了然：

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.system&lt;/code&gt;:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;on_stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;--- 首先，这里需要对 data 判断数据的完整性，然后参考以下鬼方法来拼接：&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;--    There are two ways to deal with this:&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;--    - 1. To wait for the entire output, use |channel-buffered| mode.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;--    - 2. To read line-by-line, use the following code: &amp;gt;vim&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;-- let s:lines = [&apos;&apos;]&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;-- func! s:on_event(job_id, data, event) dict&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;--   let eof = (a:data == [&apos;&apos;])&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;--   &quot; Complete the previous line.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;--   let s:lines[-1] .= a:data[0]&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;--   &quot; Append (last item may be a partial line, until EOF).&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;--   call extend(s:lines, a:data[1:])&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;-- endf&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;-- 然后，拼接完成后，再执行逐行提取&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;progress&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string.match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%d*%%&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;-- 然后在这个地方，你就会发现，无法判断这到底是哪个 Job 触发的 callback 函数了。&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- clone plugin A&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;git&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;clone&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url_a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- clone plugin B&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;git&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;clone&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url_b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;job.nvim&lt;/code&gt;:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;job&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jobs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;on_stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;string.format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;repo %s clone progress %s&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;string.match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%d*%%&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- clone plugin A&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;git&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;clone&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url_a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;A&apos;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- clone plugin B&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;git&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;clone&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url_b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;B&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;写在最后&quot;&gt;写在最后&lt;/h2&gt;

也许，job.nvim 在许多年后会停止维护，那一定是我找到了更合适的内置替代方案。至少目前，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.system&lt;/code&gt; 的实现还没有完全满足我的使用需求。

最后，我终于理解 avante.nvim 的作者为什么删掉 Reddit 账号了。吵架真的很烦。
https://www.reddit.com/r/neovim/comments/1rdgfxg/comment/o7bzfzc/

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.system&lt;/code&gt; 的设计本身就有问题。我自己写了将近二三十个异步调用命令的插件，难道我遇到的问题还不够多吗？有些人一再给我强调可以在 exit_cb 里面区分 job，难道调用常驻命令时，要等它们执行完毕才能看到结果吗？

那就让我们看看以后的版本 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.system&lt;/code&gt; 会不会增加这样的参数传入，或者会不会有类似的新的内置函数出现吧。
</description>
        <pubDate>Wed, 25 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/why-use-job-instead-of-vim-system/</link>
        <guid isPermaLink="true">https://wsdjeg.net/why-use-job-instead-of-vim-system/</guid>
        
        <category>neovim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>从零开始理解如何制作自己的 AI 助手</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#与服务器互动的基本原理&quot; id=&quot;markdown-toc-与服务器互动的基本原理&quot;&gt;与服务器互动的基本原理&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#消息角色role&quot; id=&quot;markdown-toc-消息角色role&quot;&gt;消息角色（role）&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#那些新概念文件到底是什么&quot; id=&quot;markdown-toc-那些新概念文件到底是什么&quot;&gt;那些”新概念”文件到底是什么？&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#实际存在的配置文件&quot; id=&quot;markdown-toc-实际存在的配置文件&quot;&gt;实际存在的配置文件&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#过度包装的概念&quot; id=&quot;markdown-toc-过度包装的概念&quot;&gt;过度包装的概念&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#如何看待这些概念&quot; id=&quot;markdown-toc-如何看待这些概念&quot;&gt;如何看待这些概念&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#核心观点&quot; id=&quot;markdown-toc-核心观点&quot;&gt;核心观点&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#实际开发中的选择&quot; id=&quot;markdown-toc-实际开发中的选择&quot;&gt;实际开发中的选择&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

大约一年前，我开始关注 AI 相关的内容。从一开始的简单代码补全，到后来的文本对话，再到工具调用，新技术层出不穷，确实令人兴奋。
但最近我发现，有些人刻意制造新概念，试图将它们包装成新技术来吸引流量，这让我感到十分反感。

于是，我决定从零开始学习 AI 相关知识，并着手开发 AI 相关的 Neovim 插件。
整个过程踩了不少坑，但也逐渐理解了用户与 AI 之间的沟通逻辑。
因此，我想把这些内容整理成文字，帮助大家更好地理解用户与 AI 沟通时的底层逻辑，
同时也便于区分什么是真正的新技术，什么是人为包装的伪概念。

那就从简单的 &lt;a href=&quot;https://api-docs.deepseek.com/&quot;&gt;DeepSeek 官网开发者文档&lt;/a&gt; 开始吧。

&lt;h2 id=&quot;与服务器互动的基本原理&quot;&gt;与服务器互动的基本原理&lt;/h2&gt;

与大模型之间的沟通，通常是通过 API 请求完成的。比如向 DeepSeek 发送一句 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hello!&lt;/code&gt;，实际上执行的命令是：

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl https://api.deepseek.com/chat/completions &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type: application/json&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Authorization: Bearer &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DEEPSEEK_API_KEY&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{
        &quot;model&quot;: &quot;deepseek-chat&quot;,
        &quot;messages&quot;: [
          {&quot;role&quot;: &quot;system&quot;, &quot;content&quot;: &quot;You are a helpful assistant.&quot;},
          {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;Hello!&quot;}
        ],
        &quot;stream&quot;: false
      }&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

得到的回复大致如下：

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;930c60df-bf64-41c9-a88e-3ec75f81e00e&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;choices&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;finish_reason&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;stop&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Hello! How can I help you today?&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;created&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1705651092&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;deepseek-chat&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;chat.completion&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;usage&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;completion_tokens&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;prompt_tokens&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;total_tokens&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

为了方便展示，我移除了一些额外内容，只保留核心部分。实际上发送给服务器的消息数据是：

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;system&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;You are a helpful assistant.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Hello!&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

而得到的回复也是一个单独的消息：

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Hello! How can I help you today?&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此时，如果我们想要保留会话历史并继续发送内容 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;What&apos;s the weather in SF?&lt;/code&gt;，就需要将服务器返回的消息追加到消息列表中，然后添加新的用户消息。于是，我们发送给服务器的消息变成这样：

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;system&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;You are a helpful assistant.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Hello!&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Hello! How can I help you today?&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;What&apos;s the weather in SF?&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

服务器除了返回文本内容外，有时还会返回 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tool_call&lt;/code&gt;。这意味着返回的 JSON 中包含要调用的函数名称和参数，你收到的消息大致如下：

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;call_123abc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;function&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;function&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;get_weather&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;arguments&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;{&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;San Francisco&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;celsius&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;}&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

然后，你的助手软件实际上会做的是：根据这个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tool_call&lt;/code&gt; 内容调用对应的本地功能函数，
执行完成后，将结果连同上面的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tool_call&lt;/code&gt; 一起再次“自动”发送给服务器。
于是，发送给服务器的消息大致如下：

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;system&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;You are a helpful assistant.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Hello!&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Hello! How can I help you today?&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;What&apos;s the weather in SF?&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;tool_calls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;call_123&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;function&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;function&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;get_weather&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;arguments&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;{&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;San Francisco&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;}&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;tool&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;tool_call_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;call_123&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;{&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;temperature&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: 18, &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;conditions&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Sunny&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;humidity&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: 65}&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

服务器给你返回的内容如果任然是 tool_call 那么就可以继续调用本地工具执行完成后返回给服务器。
这样的“自动”请求步骤循环下去，就形成了一个自动化的智能助手假象。

直到服务器返回的内容不再是 tool_call 而是 content，就可以将内容前台展示给用户了：

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;The weather in San Francisco is currently 18°C and sunny with 65% humidity.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上内容就是一个最基本的智能助手低层网络请求的逻辑。

&lt;h2 id=&quot;消息角色role&quot;&gt;消息角色（role）&lt;/h2&gt;

从上面的请求消息内容可以看到，消息的角色（role）目前有四种：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assistant&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tool&lt;/code&gt;。

各角色详解：

&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user&lt;/code&gt;&lt;/strong&gt;：这是用户输入的内容，对应聊天界面中输入框输入的信息。

&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assistant&lt;/code&gt;&lt;/strong&gt;：服务器返回的内容，有两种形式：

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;content&lt;/code&gt;：文本消息内容，直接显示在聊天界面&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tool_call&lt;/code&gt;：函数调用指令，告诉客户端需要执行什么功能&lt;/li&gt;
&lt;/ol&gt;

&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tool&lt;/code&gt;&lt;/strong&gt;：当客户端收到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tool_call&lt;/code&gt; 后，执行相应功能并将结果以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tool&lt;/code&gt; 角色发送给服务器。

&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system&lt;/code&gt;&lt;/strong&gt;：（这里需要重点澄清）
很多应用没有提供设置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system&lt;/code&gt; 角色的界面，但这个角色不是简单的“底层内容”，而是对话的“基础指令集”。它的主要作用是：

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;设定助手的行为准则&lt;/strong&gt;：如”你是一个专业的编程助手”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;定义回答风格&lt;/strong&gt;：如”用简洁的语言回答，避免冗长”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;设置安全边界&lt;/strong&gt;：如”不回答涉及暴力、违法内容的问题”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;提供上下文信息&lt;/strong&gt;：如”当前项目使用 TypeScript 5.0”&lt;/li&gt;
&lt;/ol&gt;

一个标准的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system&lt;/code&gt; 消息示例：

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;system&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;你是一个专业的软件开发助手。回答问题时请提供代码示例，并解释关键概念。如果用户的问题涉及不道德或违法内容，请礼貌拒绝。&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;那些新概念文件到底是什么&quot;&gt;那些”新概念”文件到底是什么？&lt;/h2&gt;

我开头所说的伪新概念，指的是目前在社区中流传的各种”配置文件”，比如：

&lt;h3 id=&quot;实际存在的配置文件&quot;&gt;实际存在的配置文件&lt;/h3&gt;

&lt;strong&gt;AGENTS.md&lt;/strong&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;实际用途&lt;/strong&gt;：为AI编码代理提供项目上下文和指令&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;类比&lt;/strong&gt;：项目的”README for agents”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;现状&lt;/strong&gt;：已被6万多个开源项目使用，确实有实际价值&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;示例内容&lt;/strong&gt;：项目结构、构建命令、编码规范等&lt;/li&gt;
&lt;/ul&gt;

&lt;strong&gt;CLAUDE.md&lt;/strong&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;实际用途&lt;/strong&gt;：Claude Code的配置文件，定义AI子代理的行为&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;位置&lt;/strong&gt;：通常位于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.claude/&lt;/code&gt; 目录下&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;功能&lt;/strong&gt;：配置工具调用、代码风格偏好等&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;过度包装的概念&quot;&gt;过度包装的概念&lt;/h3&gt;

&lt;strong&gt;SOUL.md&lt;/strong&gt;（灵魂文件）

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;宣称功能&lt;/strong&gt;：定义AI代理的”性格”、”价值观”、”沟通风格”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;实际本质&lt;/strong&gt;：就是加了营销术语的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system&lt;/code&gt; 指令&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;示例&lt;/strong&gt;：原本的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system&lt;/code&gt; 消息换个文件名就成了”灵魂”&lt;/li&gt;
&lt;/ul&gt;

&lt;strong&gt;SKILLS.md&lt;/strong&gt;（技能文件）

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;宣称功能&lt;/strong&gt;：列出AI能执行的所有”技能”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;实际本质&lt;/strong&gt;：工具函数（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tool_call&lt;/code&gt;）的文档化列表&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;问题&lt;/strong&gt;：与代码中的工具定义重复，维护成本高&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;如何看待这些概念&quot;&gt;如何看待这些概念&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;文件类型&lt;/th&gt;
      &lt;th&gt;实际价值&lt;/th&gt;
      &lt;th&gt;创新程度&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;AGENTS.md&lt;/td&gt;
      &lt;td&gt;高&lt;/td&gt;
      &lt;td&gt;中等（提供了标准化格式）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CLAUDE.md&lt;/td&gt;
      &lt;td&gt;中&lt;/td&gt;
      &lt;td&gt;低（平台特定配置）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;SOUL.md&lt;/td&gt;
      &lt;td&gt;低&lt;/td&gt;
      &lt;td&gt;极低（换名不换药）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;SKILLS.md&lt;/td&gt;
      &lt;td&gt;低&lt;/td&gt;
      &lt;td&gt;极低（文档化工具列表）&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;核心观点&quot;&gt;核心观点&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;技术本质没变&lt;/strong&gt;：这些文件底层还是通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system&lt;/code&gt; 消息或工具定义来实现&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;创新 vs 包装&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;真创新&lt;/strong&gt;：AGENTS.md 提供了标准化的项目上下文传递方式&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;伪概念&lt;/strong&gt;：SOUL.md 等只是给现有技术换了个好听的名字&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;开发建议&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;使用 AGENTS.md 提升AI编码效率 ✓&lt;/li&gt;
      &lt;li&gt;不要被”灵魂”、”技能”等营销术语迷惑 ✗&lt;/li&gt;
      &lt;li&gt;理解底层的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tool_call&lt;/code&gt; 机制才是关键&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;实际开发中的选择&quot;&gt;实际开发中的选择&lt;/h3&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gh&quot;&gt;# 推荐的配置方式&lt;/span&gt;

&lt;span class=&quot;gu&quot;&gt;## 1. 核心配置（必需）&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;
-&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`system`&lt;/span&gt; 消息：定义助手基本行为
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 工具函数：实际可用的功能

&lt;span class=&quot;gu&quot;&gt;## 2. 项目配置（推荐）&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;
-&lt;/span&gt; AGENTS.md：项目级AI辅助配置

&lt;span class=&quot;gu&quot;&gt;## 3. 避免过度设计&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;
-&lt;/span&gt; 不需要 SOUL.md、SKILLS.md 等冗余文件
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; 保持配置简洁，避免维护负担
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

真正的技术创新应该解决实际问题，而不是发明新名词。理解了消息传递的底层机制，就能一眼看穿哪些是真正有用的工具，哪些只是华丽的包装。
</description>
        <pubDate>Wed, 25 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/ai-assistant-implementation-from-scratch/</link>
        <guid isPermaLink="true">https://wsdjeg.net/ai-assistant-implementation-from-scratch/</guid>
        
        <category>AI</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Neovim 智能对话伙伴 chat.nvim</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#安装及配置-chatnvim&quot; id=&quot;markdown-toc-安装及配置-chatnvim&quot;&gt;安装及配置 chat.nvim&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#使用操作界面&quot; id=&quot;markdown-toc-使用操作界面&quot;&gt;使用操作界面&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#多-ai-提供商支持&quot; id=&quot;markdown-toc-多-ai-提供商支持&quot;&gt;多 AI 提供商支持&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#pickernvim-集成&quot; id=&quot;markdown-toc-pickernvim-集成&quot;&gt;picker.nvim 集成&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#内置工具支持&quot; id=&quot;markdown-toc-内置工具支持&quot;&gt;内置工具支持&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#文件操作工具&quot; id=&quot;markdown-toc-文件操作工具&quot;&gt;文件操作工具&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#网页工具&quot; id=&quot;markdown-toc-网页工具&quot;&gt;网页工具&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#记忆系统&quot; id=&quot;markdown-toc-记忆系统&quot;&gt;记忆系统&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#其他工具&quot; id=&quot;markdown-toc-其他工具&quot;&gt;其他工具&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#会话管理&quot; id=&quot;markdown-toc-会话管理&quot;&gt;会话管理&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#并行会话&quot; id=&quot;markdown-toc-并行会话&quot;&gt;并行会话&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#im-集成&quot; id=&quot;markdown-toc-im-集成&quot;&gt;IM 集成&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#discord-集成&quot; id=&quot;markdown-toc-discord-集成&quot;&gt;Discord 集成&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#飞书集成&quot; id=&quot;markdown-toc-飞书集成&quot;&gt;飞书集成&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#消息同步&quot; id=&quot;markdown-toc-消息同步&quot;&gt;消息同步&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#http-api&quot; id=&quot;markdown-toc-http-api&quot;&gt;HTTP API&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#api-端点&quot; id=&quot;markdown-toc-api-端点&quot;&gt;API 端点&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#使用示例&quot; id=&quot;markdown-toc-使用示例&quot;&gt;使用示例&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#快捷键&quot; id=&quot;markdown-toc-快捷键&quot;&gt;快捷键&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#总结&quot; id=&quot;markdown-toc-总结&quot;&gt;总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

很长一段时间，AI 一直是一个非常热门的话题。衍生出来的工具也非常的多，从我接触的顺序来看，
从最早的 tabline 补全到后来的 GitHub Copilot 补全。再到后来的 ChatGPT 以及之后来的各自类似的
Chat 工具。

前面我使用最多的还是网页版的 ChatGPT，使用过程中最大的一个问题就是请求结果渲染展示一直是有问题的。
尤其是让他展示 markdown 源码时。比如：

&lt;img src=&quot;../images/chat-markdown-display-error.png&quot; alt=&quot;markdown display error&quot; /&gt;

上述图片 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Usage&lt;/code&gt; 实际上也在代码块里面是，但是由于 markdown 内还有代码块，导致解析展示出问题。
正是由于这个原因，我制作了 Neovim AI 聊天插件 &lt;a href=&quot;https://github.com/wsdjeg/chat.nvim&quot;&gt;chat.nvim&lt;/a&gt;，
我需要以纯文本展示请求结果的完整内容。

&lt;h2 id=&quot;安装及配置-chatnvim&quot;&gt;安装及配置 chat.nvim&lt;/h2&gt;

使用任意插件管理器，比如 nvim-plug:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deepseek_api_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;xxxxxxxxxxx&apos;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free_chatgpt_api_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;xxxxxxxxxxxxxxx&apos;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/chat.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;depends&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/job.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- Required&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/picker.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- Optional but recommended&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;使用操作界面&quot;&gt;使用操作界面&lt;/h2&gt;

chat.nvim 默认是上下分屏两个浮窗，分别为输入窗口和结果展示窗口。如图：

&lt;img src=&quot;../images/chat-nvim-intro.png&quot; alt=&quot;chat.nvim&quot; /&gt;

&lt;h2 id=&quot;多-ai-提供商支持&quot;&gt;多 AI 提供商支持&lt;/h2&gt;

chat.nvim 内置支持多种 AI 服务提供商：

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;DeepSeek&lt;/strong&gt; - &lt;a href=&quot;https://platform.deepseek.com/&quot;&gt;DeepSeek AI&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;GitHub AI&lt;/strong&gt; - &lt;a href=&quot;https://github.com/features/ai&quot;&gt;GitHub AI&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Moonshot&lt;/strong&gt; - &lt;a href=&quot;https://platform.moonshot.cn/&quot;&gt;Moonshot AI&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;OpenRouter&lt;/strong&gt; - &lt;a href=&quot;https://openrouter.ai/&quot;&gt;OpenRouter&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Qwen&lt;/strong&gt; - &lt;a href=&quot;https://www.aliyun.com/product/bailian&quot;&gt;Alibaba Cloud Qwen&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SiliconFlow&lt;/strong&gt; - &lt;a href=&quot;https://www.siliconflow.cn/&quot;&gt;SiliconFlow&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tencent Hunyuan&lt;/strong&gt; - &lt;a href=&quot;https://cloud.tencent.com/document/product/1729&quot;&gt;腾讯混元&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;BigModel&lt;/strong&gt; - &lt;a href=&quot;https://bigmodel.cn/&quot;&gt;BigModel AI&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Volcengine&lt;/strong&gt; - &lt;a href=&quot;https://console.volcengine.com&quot;&gt;火山引擎&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;OpenAI&lt;/strong&gt; - &lt;a href=&quot;https://developers.openai.com/api/docs/&quot;&gt;OpenAI&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;LongCat&lt;/strong&gt; - &lt;a href=&quot;https://longcat.chat/platform/docs/&quot;&gt;LongCat AI&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;CherryIN&lt;/strong&gt; - &lt;a href=&quot;https://open.cherryin.ai/&quot;&gt;CherryIN AI&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;YuanJing&lt;/strong&gt; - &lt;a href=&quot;https://maas.ai-yuanjing.com/&quot;&gt;元境 AI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

同时还支持自定义提供商，你可以创建 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/nvim/lua/chat/providers/&amp;lt;provider_name&amp;gt;.lua&lt;/code&gt; 来添加新的 AI 服务。

&lt;h2 id=&quot;pickernvim-集成&quot;&gt;picker.nvim 集成&lt;/h2&gt;

chat.nvim 自带了一些 picker.nvim 插件的拓展，目前支持的拓展有：

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Picker chat&lt;/code&gt; - 搜索历史对话
&lt;img src=&quot;../images/picker-chat.png&quot; alt=&quot;picker-chat&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Picker chat_provider&lt;/code&gt; - 搜索并切换 provider
&lt;img src=&quot;../images/picker-chat-provider.png&quot; alt=&quot;picker-chat&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Picker chat_model&lt;/code&gt; - 搜索并切换当前 provider 提供的模型
&lt;img src=&quot;../images/picker-chat-model.png&quot; alt=&quot;picker-chat&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;内置工具支持&quot;&gt;内置工具支持&lt;/h2&gt;

chat.nvim 支持丰富的内置工具，让 AI 可以直接与编辑器交互：

&lt;h3 id=&quot;文件操作工具&quot;&gt;文件操作工具&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@read_file&lt;/strong&gt; - 读取文件内容（支持指定行范围）&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@find_files&lt;/strong&gt; - 搜索文件&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@search_text&lt;/strong&gt; - 搜索文件内容（支持正则表达式、文件类型过滤等）&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@git_diff&lt;/strong&gt; - 查看 git diff 信息&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;网页工具&quot;&gt;网页工具&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@web_search&lt;/strong&gt; - 网络搜索（支持 Firecrawl、Google、SerpAPI）&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@fetch_web&lt;/strong&gt; - 获取网页内容&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;记忆系统&quot;&gt;记忆系统&lt;/h3&gt;

chat.nvim 实现了三层记忆系统，灵感来自认知心理学：

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;工作记忆 (Working Memory)&lt;/strong&gt; ⚡ - 当前会话的任务和决策（最高优先级）&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;日常记忆 (Daily Memory)&lt;/strong&gt; 📅 - 临时任务和短期目标（7-30天后自动过期）&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;长期记忆 (Long-term Memory)&lt;/strong&gt; 💾 - 永久知识存储（事实、偏好、技能）&lt;/li&gt;
&lt;/ul&gt;

相关工具：

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@extract_memory&lt;/strong&gt; - 提取并存储记忆&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@recall_memory&lt;/strong&gt; - 回忆相关信息&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;其他工具&quot;&gt;其他工具&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@set_prompt&lt;/strong&gt; - 设置系统提示词&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@plan&lt;/strong&gt; - 任务计划管理&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@zettelkasten_create&lt;/strong&gt; - 创建笔记（需要 zettelkasten.nvim）&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@zettelkasten_get&lt;/strong&gt; - 获取笔记（需要 zettelkasten.nvim）&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;会话管理&quot;&gt;会话管理&lt;/h2&gt;

chat.nvim 提供了完整的会话管理功能：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Chat&lt;/code&gt; - 打开当前会话&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Chat new&lt;/code&gt; - 创建新会话&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Chat prev&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Chat next&lt;/code&gt; - 切换会话&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Chat clear&lt;/code&gt; - 清空当前会话&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Chat delete&lt;/code&gt; - 删除当前会话&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Chat save &amp;lt;path&amp;gt;&lt;/code&gt; - 保存会话到文件&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Chat load &amp;lt;path&amp;gt;&lt;/code&gt; - 从文件或 URL 加载会话&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Chat share&lt;/code&gt; - 分享会话到 pastebin&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Chat preview&lt;/code&gt; - 在浏览器中预览会话&lt;/li&gt;
&lt;/ul&gt;

&lt;img src=&quot;../images/chat-nvim-preview.png&quot; alt=&quot;chat preview&quot; /&gt;

&lt;h3 id=&quot;并行会话&quot;&gt;并行会话&lt;/h3&gt;

chat.nvim 支持同时运行多个独立的聊天会话：

&lt;ul&gt;
  &lt;li&gt;每个会话可以使用不同的 AI 模型&lt;/li&gt;
  &lt;li&gt;会话之间保持独立的对话历史和设置&lt;/li&gt;
  &lt;li&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Chat prev&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Chat next&lt;/code&gt; 快速切换&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;im-集成&quot;&gt;IM 集成&lt;/h2&gt;

chat.nvim 支持多种第三方聊天平台集成，可以将 Neovim 的 AI 对话能力扩展到各个平台：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;平台&lt;/th&gt;
      &lt;th&gt;图标&lt;/th&gt;
      &lt;th&gt;双向通信&lt;/th&gt;
      &lt;th&gt;特点&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Discord&lt;/td&gt;
      &lt;td&gt;💬&lt;/td&gt;
      &lt;td&gt;✅ 是&lt;/td&gt;
      &lt;td&gt;完整的机器人功能，会话绑定&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;飞书&lt;/td&gt;
      &lt;td&gt;🐦&lt;/td&gt;
      &lt;td&gt;✅ 是&lt;/td&gt;
      &lt;td&gt;飞书机器人，消息轮询&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;钉钉&lt;/td&gt;
      &lt;td&gt;📱&lt;/td&gt;
      &lt;td&gt;✅ 是*&lt;/td&gt;
      &lt;td&gt;Webhook（单向）或 API（双向）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;企业微信&lt;/td&gt;
      &lt;td&gt;💼&lt;/td&gt;
      &lt;td&gt;✅ 是*&lt;/td&gt;
      &lt;td&gt;企业微信 Webhook 或 API&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Telegram&lt;/td&gt;
      &lt;td&gt;✈️&lt;/td&gt;
      &lt;td&gt;✅ 是&lt;/td&gt;
      &lt;td&gt;Bot API，支持群组和私聊&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;discord-集成&quot;&gt;Discord 集成&lt;/h3&gt;

&lt;img src=&quot;../images/chat-nvim-discord.jpg&quot; alt=&quot;chat-nvim-discord&quot; /&gt;

通过 Discord 集成，你可以：

&lt;ul&gt;
  &lt;li&gt;在 Discord 频道中与 AI 助手交互&lt;/li&gt;
  &lt;li&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Chat bridge discord&lt;/code&gt; 绑定当前会话&lt;/li&gt;
  &lt;li&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/session&lt;/code&gt; 命令确认绑定&lt;/li&gt;
  &lt;li&gt;通过提及机器人或回复消息来触发对话&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;飞书集成&quot;&gt;飞书集成&lt;/h3&gt;

&lt;img src=&quot;../images/chat-nvim-lark.jpg&quot; alt=&quot;chat-nvim-lark&quot; /&gt;

飞书集成支持：

&lt;ul&gt;
  &lt;li&gt;双向消息通信&lt;/li&gt;
  &lt;li&gt;自动轮询新消息&lt;/li&gt;
  &lt;li&gt;长消息支持（最多 30,720 字符）&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;消息同步&quot;&gt;消息同步&lt;/h3&gt;

通过这些集成，可以实现 Neovim 与各平台的消息同步：

&lt;img src=&quot;../images/chat-nvim-neovim.png&quot; alt=&quot;chat-nvim-integration-sync&quot; /&gt;

这些集成功能让 chat.nvim 成为一个多平台的 AI 对话中心，不仅可以在 Neovim 内使用，还可以作为各种聊天平台的智能助手。

&lt;h2 id=&quot;http-api&quot;&gt;HTTP API&lt;/h2&gt;

chat.nvim 内置了 HTTP 服务器功能，提供 RESTful API 接口：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;host&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;127.0.0.1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7777&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;api_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;your-secret-key&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;api-端点&quot;&gt;API 端点&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;POST /&lt;/strong&gt; - 发送消息到指定会话&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;GET /sessions&lt;/strong&gt; - 获取所有活跃会话列表&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;GET /session&lt;/strong&gt; - 获取会话的 HTML 预览（需要 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt; 参数）&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;使用示例&quot;&gt;使用示例&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 发送消息&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;-X&lt;/span&gt; POST http://127.0.0.1:7777/ &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;X-API-Key: your-secret-key&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type: application/json&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{&quot;session&quot;: &quot;my-session&quot;, &quot;content&quot;: &quot;Hello from curl!&quot;}&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 获取会话列表&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;X-API-Key: your-secret-key&quot;&lt;/span&gt; http://127.0.0.1:7777/sessions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这使得外部应用可以轻松集成 chat.nvim 的对话能力，比如 CI/CD 流水线、监控系统等。

&lt;h2 id=&quot;快捷键&quot;&gt;快捷键&lt;/h2&gt;

在输入窗口中：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Enter&amp;gt;&lt;/code&gt; - 发送消息&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;q&lt;/code&gt; - 关闭聊天窗口&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Tab&amp;gt;&lt;/code&gt; - 切换输入和结果窗口&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-C&lt;/code&gt; - 取消当前请求&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-N&lt;/code&gt; - 新建会话&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; - 重试上次取消的请求&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alt-h&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alt-l&lt;/code&gt; - 上一个/下一个会话&lt;/li&gt;
&lt;/ul&gt;

在结果窗口中：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;q&lt;/code&gt; - 关闭聊天窗口&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Tab&amp;gt;&lt;/code&gt; - 切换输入和结果窗口&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

从最初为了解决 markdown 渲染问题而开发的聊天插件，到现在支持多种 AI 提供商、内置工具系统、三层记忆架构、多平台集成、HTTP API 等功能，chat.nvim 已经发展成为一个功能强大的 Neovim AI 助手。它不仅能帮助你在编辑器内高效地与 AI 对话，还能通过各种工具直接操作文件、搜索网络、管理记忆，真正成为了开发者的智能伙伴。

更多详细信息，请访问 &lt;a href=&quot;https://github.com/wsdjeg/chat.nvim&quot;&gt;chat.nvim GitHub 仓库&lt;/a&gt;。
</description>
        <pubDate>Tue, 03 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/integrate-ai-chat-into-neovim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/integrate-ai-chat-into-neovim/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim buffer 删除插件 bufdel.nvim</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#为什么再写一个-bufdel-插件&quot; id=&quot;markdown-toc-为什么再写一个-bufdel-插件&quot;&gt;为什么再写一个 bufdel 插件&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#bufdelnvim-的核心设计&quot; id=&quot;markdown-toc-bufdelnvim-的核心设计&quot;&gt;bufdel.nvim 的核心设计&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#删除之后切到哪个-buffer&quot; id=&quot;markdown-toc-删除之后切到哪个-buffer&quot;&gt;删除之后，切到哪个 buffer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#用户命令bdeletebwipeout&quot; id=&quot;markdown-toc-用户命令bdeletebwipeout&quot;&gt;用户命令&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bdelete&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bwipeout&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#一个-vim-本身的限制说明&quot; id=&quot;markdown-toc-一个-vim-本身的限制说明&quot;&gt;一个 Vim 本身的限制说明&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#自定义用户事件&quot; id=&quot;markdown-toc-自定义用户事件&quot;&gt;自定义用户事件&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#和其他插件的简单对比&quot; id=&quot;markdown-toc-和其他插件的简单对比&quot;&gt;和其他插件的简单对比&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#写在最后&quot; id=&quot;markdown-toc-写在最后&quot;&gt;写在最后&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

在使用 Neovim 的过程中，「删除 buffer 但不破坏窗口布局」一直是一个高频需求。

社区里已经有不少相关插件，比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bufdelete.nvim&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim-bufdel&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mini.bufremove&lt;/code&gt;，以及 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snacks.bufdelete&lt;/code&gt;。
但是在我自己长期使用过程中，总觉得缺少了我需要的功能。

于是，我写了一个新的插件：&lt;a href=&quot;https://github.com/wsdjeg/bufdel.nvim&quot;&gt;bufdel.nvim&lt;/a&gt;。

这篇文章简单聊聊它解决了什么问题、有哪些设计取舍，以及它和现有方案的区别。

&lt;h2 id=&quot;为什么再写一个-bufdel-插件&quot;&gt;为什么再写一个 bufdel 插件&lt;/h2&gt;

先说结论：bufdel.nvim 设计初衷是为了删除 buffer 这个操作的每一步更加可控。

我写这个插件，主要有几个原因：

&lt;ol&gt;
  &lt;li&gt;
    bufdelete.nvim 已经 archived

    bufdelete.nvim 是一个非常优秀的插件，我也之前也使用过一段时间。但它目前已经被标记为 archived，不再维护。

    我希望有一个持续维护、可扩展的替代方案，同时保留它最核心、最优雅的设计。
  &lt;/li&gt;
  &lt;li&gt;
    我需要更灵活的 buffer 选择方式

    很多插件只支持按照 buffer number 删除，但是再实际使用中，我经常需要：

    &lt;ul&gt;
      &lt;li&gt;按照 buffer name 删除&lt;/li&gt;
      &lt;li&gt;按照正则表达式匹配到的 buffer 名称删除&lt;/li&gt;
      &lt;li&gt;按照特定的条件函数删除（比如：未修改、已列出、非当前 buffer）&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    删除之后，切换到哪个 buffer，应该是可控的

    前面提到的几个插件大多数在删除 buffer 后，选择切换到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bufnr(&apos;#&apos;)&lt;/code&gt;。但我更希望能明确指定下一个 buffer 是哪个或者通过函数，完全自定义切换逻辑。
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;bufdelnvim-的核心设计&quot;&gt;bufdel.nvim 的核心设计&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    一个核心 API：delete(buffers, opt)

    bufdel.nvim 只暴露一个核心函数，但是它支持的参数非常灵活。不少其他的插件会设计两个 API 函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delete&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wipeout&lt;/code&gt;，其实完全可以合并，通过 opt 内一个选项区分。

    &lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;bufdel&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    buffers 参数：你想怎么选 buffer 都行

    buffers 支持多种形式：

    &lt;ul&gt;
      &lt;li&gt;单个 buffer number&lt;/li&gt;
      &lt;li&gt;buffer 名称（字符串）&lt;/li&gt;
      &lt;li&gt;Vim 正则（匹配 buffer name）&lt;/li&gt;
      &lt;li&gt;table（混合 bufnr / bufname / regex）&lt;/li&gt;
      &lt;li&gt;函数过滤器&lt;/li&gt;
    &lt;/ul&gt;

    比如，删除所有已列出、已保存的非当前 buffer：

    &lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;bufdel&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modified&lt;/span&gt;
    &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buflisted&lt;/span&gt;
    &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wipe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    这类逻辑，在很多其他插件里是做不到的。
  &lt;/li&gt;
  &lt;li&gt;
    正则匹配 buffer 名称

    如果你想清理一类文件，比如所有 .txt buffer：

    &lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;bufdel&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;.txt$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wipe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    这在日常清理临时文件、日志文件时非常方便。
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;删除之后切到哪个-buffer&quot;&gt;删除之后，切到哪个 buffer&lt;/h2&gt;

这是 bufdel.nvim 的一个重点特性。

&lt;ol&gt;
  &lt;li&gt;
    使用函数自定义切换逻辑（推荐）

    &lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;bufdel&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;wipe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deleted_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bufnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;#&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- 切换到 alternate buffer&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    你可以在这里实现任何策略，只要返回一个有效的 buffer number。
  &lt;/li&gt;
  &lt;li&gt;
    内置几种常用策略

    如果不想写函数，也可以直接用字符串：

    &lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;alt&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    当前支持：

    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alt&lt;/code&gt;：alternate buffer（#）&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;current&lt;/code&gt;：保持当前 buffer&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lastused&lt;/code&gt;：最近使用的 buffer&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prev&lt;/code&gt;：下一个 / 上一个 buffer&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    直接指定 buffer number

    &lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;用户命令bdeletebwipeout&quot;&gt;用户命令&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bdelete&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bwipeout&lt;/code&gt;&lt;/h2&gt;

bufdel.nvim 提供了两个命令：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:Bdelete
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:Bwipeout
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

行为和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:bdelete&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:bwipeout&lt;/code&gt; 一致，但不会改变窗口布局。

示例：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:Bdelete
:Bdelete 3
:Bdelete 2 5 7
:3,6Bdelete
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;一个-vim-本身的限制说明&quot;&gt;一个 Vim 本身的限制说明&lt;/h2&gt;

和原生 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:bdelete&lt;/code&gt; 一样：

纯数字的 buffer 名称不能作为用户命令参数使用。

比如：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:e 123
:Bdelete 123
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这时必须使用 bufnr，而不是 bufname。

&lt;h2 id=&quot;自定义用户事件&quot;&gt;自定义用户事件&lt;/h2&gt;

bufdel.nvim 会在删除 buffer 前后触发两个事件：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;User BufDelPre
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;User BufDelPost
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

示例：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;User&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BufDelPost&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- 被删除的 bufnr 在 ev.data.buf 中&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果删除失败，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BufDelPost&lt;/code&gt; 不会触发。

&lt;h2 id=&quot;和其他插件的简单对比&quot;&gt;和其他插件的简单对比&lt;/h2&gt;

下面是基于我个人使用需求的一个对比表：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Feature / Plugin&lt;/th&gt;
      &lt;th&gt;bufdel.nvim&lt;/th&gt;
      &lt;th&gt;&lt;a href=&quot;https://github.com/famiu/bufdelete.nvim&quot;&gt;bufdelete.nvim&lt;/a&gt;&lt;/th&gt;
      &lt;th&gt;&lt;a href=&quot;https://github.com/ojroques/nvim-bufdel&quot;&gt;nvim-bufdel&lt;/a&gt;&lt;/th&gt;
      &lt;th&gt;&lt;a href=&quot;https://github.com/folke/snacks.nvim/blob/main/lua/snacks/bufdelete.lua&quot;&gt;snacks.bufdelete&lt;/a&gt;&lt;/th&gt;
      &lt;th&gt;&lt;a href=&quot;https://github.com/nvim-mini/mini.nvim/blob/main/lua/mini/bufremove.lua&quot;&gt;mini.bufremove&lt;/a&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Preserve window layout&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Delete by bufnr&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Delete by bufname&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;User Command&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Lua filter function&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Regex buffer matching&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Post-delete buffer switch&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;User autocmd hooks&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
      &lt;td&gt;✗&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

如果你发现表格里有不准确的地方，欢迎直接提 issue。

&lt;h2 id=&quot;写在最后&quot;&gt;写在最后&lt;/h2&gt;

bufdel.nvim 并不是一个“什么都做”的插件，相反，我刻意让它保持：

&lt;ul&gt;
  &lt;li&gt;功能边界清晰&lt;/li&gt;
  &lt;li&gt;API 简单&lt;/li&gt;
  &lt;li&gt;逻辑可控&lt;/li&gt;
&lt;/ul&gt;

如果你：

&lt;ul&gt;
  &lt;li&gt;经常清理 buffer&lt;/li&gt;
  &lt;li&gt;在意窗口布局&lt;/li&gt;
  &lt;li&gt;希望对 buffer 删除过程有更多掌控&lt;/li&gt;
&lt;/ul&gt;

那它可能正好适合你。

👉 GitHub：&lt;a href=&quot;https://github.com/wsdjeg/bufdel.nvim&quot;&gt;wsdjeg/budel.nvim&lt;/a&gt;

如果你觉得有用，欢迎 star ⭐
</description>
        <pubDate>Wed, 28 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/bufdel-without-changing-window-layout/</link>
        <guid isPermaLink="true">https://wsdjeg.net/bufdel-without-changing-window-layout/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 日历插件 calendar.nvim</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#插件安装&quot; id=&quot;markdown-toc-插件安装&quot;&gt;插件安装&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#基本使用&quot; id=&quot;markdown-toc-基本使用&quot;&gt;基本使用&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#记录一些坑&quot; id=&quot;markdown-toc-记录一些坑&quot;&gt;记录一些坑&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#最终效果图&quot; id=&quot;markdown-toc-最终效果图&quot;&gt;最终效果图&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

早在写 zettelkasten.nvim 插件的时候，我就想做一个日历试图，用来查看笔记的日期。可能是因为需求不是那么的迫切，
所以一直拖着没有写这样功能。

趁着这次假日，抽空写了这样一个日历插件 &lt;a href=&quot;https://github.com/wsdjeg/calendar.nvim&quot;&gt;calendar.nvim&lt;/a&gt;，功能目前还是非常简单的，只是一个简单的日历月视图。
这算是 2026 年我的第一个 Neovim 插件，这篇文字主要介绍 calendar.nvim 插件的安装使用以及制作这一插件遇到的一些问题。

&lt;h2 id=&quot;插件安装&quot;&gt;插件安装&lt;/h2&gt;

calendar.nvim 是使用 Lua 实现的 Neovim 插件，零依赖，可以使用任意插件管理器直接安装，比如：&lt;a href=&quot;https://github.com/wsdjeg/nvim-plug&quot;&gt;nvim-plug&lt;/a&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/calendar.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;基本使用&quot;&gt;基本使用&lt;/h2&gt;

插件的默认配置如下：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;calendar&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;mark_icon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;•&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;next_month&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;L&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;-- 下个月&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;previous_month&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;H&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;-- 上个月&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;next_day&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;l&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;-- 后一天&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;previous_day&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;h&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;-- 前一天&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;next_week&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;j&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;-- 下一周&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;previous_week&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;k&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;-- 前一周&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;today&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;t&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;-- 跳到今天&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;highlights&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Visual&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;today&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Todo&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Todo&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;记录一些坑&quot;&gt;记录一些坑&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_buf_set_extmark&lt;/code&gt; 函数中 col 等参数指的并不是屏幕 column 列表，而是字符串的字节，
  &lt;/li&gt;
  &lt;li&gt;
    overlay virt_text 的高亮会清除掉当前位置的 extmark hl_group 高亮
  &lt;/li&gt;
&lt;/ol&gt;

最终解决逻辑是给每一个需要标记的位置按照如下逻辑添加 virt_text，其高亮参数传输一个高亮列表.

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;highlights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_totay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;highlights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;today&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;highlights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_set_extmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;virt_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mark_icon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hls&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;最终效果图&quot;&gt;最终效果图&lt;/h2&gt;

这里展示了一个添加了 zettelkasten 拓展的日历：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zk_ext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;zk_ext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;notes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;zettelkasten.browser&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_notes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;marks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;note&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;notes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;note&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tonumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tonumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;month&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;marks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tonumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;month&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tonumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;day&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tonumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;marks&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;calendar.extensions&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zk_ext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

最终的效果图如下：

&lt;img src=&quot;../images/calendar-demo.gif&quot; alt=&quot;calendar-demo&quot; /&gt;
</description>
        <pubDate>Sun, 04 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-minimal-calendar/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-minimal-calendar/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>文件路径大小写敏感导致 Lua 模块重载</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#事情起因&quot; id=&quot;markdown-toc-事情起因&quot;&gt;事情起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#寻找原因&quot; id=&quot;markdown-toc-寻找原因&quot;&gt;寻找原因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#如何修复&quot; id=&quot;markdown-toc-如何修复&quot;&gt;如何修复？&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#总结&quot; id=&quot;markdown-toc-总结&quot;&gt;总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;事情起因&quot;&gt;事情起因&lt;/h2&gt;

时隔十年，再次被 Windows 系统的路劲大小写问题坑了一把。记得上一次被坑是因为写 Vim Script 的 autoload 脚本时出现的问题。
最近使用 Lua 重新写了 ChineseLinter.vim 这个插件，最开始的文件结构：

文件：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugins/chineselinter.lua&lt;/code&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/ChineseLinter.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ignored_errors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;E015&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;E013&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;E020&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;E021&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;cmds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;CheckChinese&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Chinese Document Language Standards Checking Tool&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

按照以上配置，无论如何 ignored_errors 配置都无法起效。

&lt;h2 id=&quot;寻找原因&quot;&gt;寻找原因&lt;/h2&gt;

上述插件在载入时没有报错，说明被成功载入并且执行了 setup 函数。我试着用单独的脚本来测试，并且打入一些日志：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runtimepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;D:/wsdjeg/job.nvim&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runtimepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;D:/wsdjeg/logger.nvim&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runtimepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;D:/wsdjeg/nvim-plug&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;bundle_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;D:/bundle_dir&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;raw_plugin_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;D:/bundle_dir/raw_plugin&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- ui = &apos;notify&apos;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;http_proxy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;http://127.0.0.1:7890&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;https_proxy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;http://127.0.0.1:7890&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;enable_priority&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;enable_luarocks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;max_processes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dev_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;D:/wsdjeg&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;plug&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;s2&quot;&gt;&quot;wsdjeg/ChineseLinter.nvim&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;ignored_errors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;E015&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;E013&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;E020&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;E021&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;cmds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;CheckChinese&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Chinese Document Language Standards Checking Tool&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
日志结果如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ 23:35:32:449 ] [ Info  ] [ cnlint ] module is loaded
[ 23:35:32:450 ] [ Info  ] [ cnlint ] setup function is called
[ 23:35:32:450 ] [ Info  ] [   plug ] load plug: ChineseLinter.nvim in 4.3624ms
[ 23:35:32:451 ] [ Info  ] [ cnlint ] module is loaded
[ 23:35:32:451 ] [ Info  ] [ cnlint ] check function is called
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

不难看出 ChineseLinter 模块被载入了两次，第一次载入及setup函数是 nvim-plug 在执行，执行后计算的载入时间，第二次是执行 CheckChinese 命令时，
而这一命令是在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugin/ChineseLinter.lua&lt;/code&gt; 内定义的：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_user_command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;CheckChinese&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ChineseLinter&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;check&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

问题就在这里，这个命令内 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require(&apos;ChineseLinter&apos;)&lt;/code&gt; 不应该再次载入模块文件，因为前面 nvim-plug 已经执行过一次了，正常情况下 package.loaded 内会缓存模块。

看一下 nvim-plug 载入 Lua 插件的逻辑，它会给 plugSpec 自动设置一个模块名称，
以便于自动执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require(plugSpec.module).setup(plugSpec.opts)&lt;/code&gt;。

问题就在于这个 module 名称生成函数原先是：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_default_module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%.%-&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;lua$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;&apos;^n&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;vim-&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%.%-&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;vim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

也就是说，按照上述载入插件方式，nvim-plug 执行的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require(&apos;chineselinter&apos;)&lt;/code&gt;，这在 Windows 系统下,
因为文件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lua/ChineseLinter/init.lua&lt;/code&gt; 已存在，那么上述 require 函数就会读取这个模块。

而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:CheckChinese&lt;/code&gt; 命令实际上调用的模块是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require(&apos;ChineseLinter&apos;)&lt;/code&gt;。
因为 Lua 的模块名称实际上是大小写敏感的，就会再次去寻找模块文件以载入。

&lt;h2 id=&quot;如何修复&quot;&gt;如何修复？&lt;/h2&gt;

我查阅了几个插件管理器，他们的获取模块名称的函数基本上逻辑类似，都使用了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lower()&lt;/code&gt; 函数：

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/folke/lazy.nvim/blob/1ea3c4085785f460fb0e46d2fe1ee895f5f9e7c1/lua/lazy/core/util.lua#L68&quot;&gt;lazy.nvim&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;---@param name string&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;---@return string&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;normname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;&quot;^n&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;vim%-&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;&quot;%.n&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;vim$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;%.%-&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;[^&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;a-z&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;+&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

实际上，最好是不要自动去将模块的名字全部小写，按照仓库的名称来最合适，去除掉前后缀，修改 nvim-plug 如下：

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gh&quot;&gt;diff --git a/lua/plug/loader.lua b/lua/plug/loader.lua
index d0fc7b6..957fcb7 100644
&lt;/span&gt;&lt;span class=&quot;gd&quot;&gt;--- a/lua/plug/loader.lua
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/lua/plug/loader.lua
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -68,8 +68,7 @@&lt;/span&gt; end
 --- @param name string
 --- @return string
 local function get_default_module(name)
&lt;span class=&quot;gd&quot;&gt;-    return name:lower()
-        :gsub(&apos;[%.%-]lua$&apos;, &apos;&apos;)
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+    return name:gsub(&apos;[%.%-]lua$&apos;, &apos;&apos;)
&lt;/span&gt;         :gsub(&apos;^n?vim-&apos;, &apos;&apos;)
         :gsub(&apos;[%.%-]n?vim&apos;, &apos;&apos;)
 end
&lt;span class=&quot;p&quot;&gt;@@ -94,6 +93,13 @@&lt;/span&gt; function M.parser(plugSpec)
     plugSpec.name = check_name(plugSpec)
     if not plugSpec.module then
         plugSpec.module = get_default_module(plugSpec.name)
&lt;span class=&quot;gi&quot;&gt;+        log.info(
+            string.format(
+                &apos;set %s default module name to %s&apos;,
+                plugSpec.name,
+                plugSpec.module
+            )
+        )
&lt;/span&gt;     end
     if #plugSpec.name == 0 then
         plugSpec.enabled = false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

考虑到 Windows 系统的大小写敏感，以及 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shift&lt;/code&gt; 键这么难按，我将插件的名称以及其内模块的名称都改成了小写，修改后插件的安装方式：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/chineselinter.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ignored_errors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;E015&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;E013&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;E020&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;E021&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;cmds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;CheckChinese&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Chinese Document Language Standards Checking Tool&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

上述核心问题在于 Lua 的 require() 函数读取模块缓存时判断的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.load[key]&lt;/code&gt;，这里的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key&lt;/code&gt; 是大小写敏感的。
而发现缓存不存在时，依照 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key&lt;/code&gt; 去载入文件时，在 Windows 系统下路劲又是不敏感的，
会导致同一个模块被不同的大小写模块名称多次载入。
</description>
        <pubDate>Sun, 28 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-module-reload-path-case-sensitivity/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-module-reload-path-case-sensitivity/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 悬浮滚动条 scrollbar.nvim</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#scrollbarnvim-简介&quot; id=&quot;markdown-toc-scrollbarnvim-简介&quot;&gt;scrollbar.nvim 简介&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#安装-scrollbarnvim&quot; id=&quot;markdown-toc-安装-scrollbarnvim&quot;&gt;安装 scrollbar.nvim&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#插件的配置&quot; id=&quot;markdown-toc-插件的配置&quot;&gt;插件的配置&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;scrollbarnvim-简介&quot;&gt;scrollbar.nvim 简介&lt;/h2&gt;

好几年前，我使用 Vim Script 实现过一个&lt;a href=&quot;../floating-scrollbar-for-vim-and-neovim/&quot;&gt;悬浮侧栏插件 scrollbar.vim&lt;/a&gt;，
前段时间该插件使用 Lua 进行了重写并改名称为 &lt;a href=&quot;https://github.com/wsdjeg/scrollbar.nvim&quot;&gt;scrollbar.nvim&lt;/a&gt;，
重写后的插件只支持 Neovim。

scrollbar.nvim 会在当前窗口的右侧使用浮窗绘制一个滚动条，其位置依据当前窗口显示的内容在整个文件中所在的行数，
并且随着鼠标移动、滚屏等操作上下移动。

&lt;h2 id=&quot;安装-scrollbarnvim&quot;&gt;安装 scrollbar.nvim&lt;/h2&gt;

使用 nvim-plug 进行安装：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/scrollbar.nvim&apos;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

或者使用 luarocks 进行安装：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;luarocks install scrollbar.nvim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;插件的配置&quot;&gt;插件的配置&lt;/h2&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;scrollbar&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;max_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;min_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;right_offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;excluded_filetypes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;startify&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;git-commit&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;leaderf&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;NvimTree&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;tagbar&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;defx&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;neo-tree&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;qf&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;▲&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;█&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;▼&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;highlight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Normal&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Normal&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Normal&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Thu, 25 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/floating-scrollbar-for-neovim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/floating-scrollbar-for-neovim/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>如何正确地使用 ftplugin 目录</title>
        <description>前面再阅读一些插件源码时，发现一个问题，很多插件的使用了 ftplugin 这个目录，其内的脚本文件中直接使用了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setlocal xx=xx&lt;/code&gt; 这样的语法。
在早期的 Neovim 或者 Vim 版本中这样确实没有问题，但是随着 Neovim 功能特性增加。这样写就会容易出错。
实际上，直到目前为止 Neovim 和 Vim 的官方文档 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h ftplugin&lt;/code&gt; 内的示例还是：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot; Only do this when not done yet for this buffer&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;b:did_ftplugin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;finish&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:did_ftplugin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;setlocal&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;textwidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;70&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

Neovim 插件的 ftplugin 目录是一个特殊的文件夹，其内的文件会在 FileType 事件触发是被载入。

看一下 Neovim 的源码，ftplugin 目录下的文件是如何被载入的。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;augroup filetypeplugin
  &lt;span class=&quot;k&quot;&gt;au&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;FileType&lt;/span&gt; * &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:LoadFTPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

  func&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:LoadFTPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;b:undo_ftplugin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      exe &lt;span class=&quot;nv&quot;&gt;b:undo_ftplugin&lt;/span&gt;
      unlet&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:undo_ftplugin&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:did_ftplugin&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; s &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;amatch&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; s &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;cpo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=~&lt;/span&gt;# &lt;span class=&quot;s2&quot;&gt;&quot;S&quot;&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;nb&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;b:did_ftplugin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;c&quot;&gt;&quot; In compatible mode options are reset to the global values, need to&lt;/span&gt;
	&lt;span class=&quot;c&quot;&gt;&quot; set the local values also when a plugin was already used.&lt;/span&gt;
	unlet &lt;span class=&quot;nv&quot;&gt;b:did_ftplugin&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;

      &lt;span class=&quot;c&quot;&gt;&quot; When there is a dot it is used to separate filetype names.  Thus for&lt;/span&gt;
      &lt;span class=&quot;c&quot;&gt;&quot; &quot;aaa.bbb&quot; load &quot;aaa&quot; and then &quot;bbb&quot;.&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; name &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\.&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; Load Lua ftplugins after Vim ftplugins _per directory_&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; TODO(clason): use nvim__get_runtime when supports globs and modeline&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; XXX: &quot;[.]&quot; in the first pattern makes it a wildcard on Windows&lt;/span&gt;
        exe $&lt;span class=&quot;s1&quot;&gt;&apos;runtime! ftplugin/{name}[.] ftplugin/{name}_*. ftplugin/{name}/*.&apos;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  endfunc
augroup END
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上内容不难看出，Neovim 实际上是监听了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FileType&lt;/code&gt; 这个事件，然后根据 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expand(&apos;&amp;lt;amatch&amp;gt;&apos;)&lt;/code&gt; 的值来执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:runtime&lt;/code&gt; 命令。

但是，随着 Neovim 和 Vim 增加了设置非当前 buffer 的 option 这一功能后。就会出现这样问题，当 FileType 事件触发时，触发的 buffer 并非是当前 buffer。
那么在 ftplugin 内如果使用了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setlocal&lt;/code&gt; 这样的命令，有可能会设置错了缓冲区。

test_ft.lua

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;logger&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ft&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_buf() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_win() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-----------------------------------------------------&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;real_current_win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newbuf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;events&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getcompletion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;event&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endswith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Cmd&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
		&lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test_ft&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-----------------------------------------------------&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;event is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ev.buf is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_buf() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_win() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;real_current_win&apos;s buf is&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_get_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;real_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_open_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newbuf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;split&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;above&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_set_option_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;filetype&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;test123&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newbuf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_del_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-----------------------------------------------------&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_buf() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_win() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ 23:50:19:932 ] [ Info  ] [     ft ] nvim_get_current_buf() is 7
[ 23:50:19:932 ] [ Info  ] [     ft ] nvim_get_current_win() is 1000
[ 23:50:19:932 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:50:19:933 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:50:19:933 ] [ Info  ] [     ft ] event is WinNew
[ 23:50:19:933 ] [ Info  ] [     ft ] ev.buf is 7
[ 23:50:19:933 ] [ Info  ] [     ft ] nvim_get_current_buf() is 7
[ 23:50:19:933 ] [ Info  ] [     ft ] nvim_get_current_win() is 1008
[ 23:50:19:933 ] [ Info  ] [     ft ] real_current_win&apos;s buf is7
[ 23:50:19:934 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:50:19:934 ] [ Info  ] [     ft ] event is BufWinEnter
[ 23:50:19:934 ] [ Info  ] [     ft ] ev.buf is 9
[ 23:50:19:934 ] [ Info  ] [     ft ] nvim_get_current_buf() is 9
[ 23:50:19:934 ] [ Info  ] [     ft ] nvim_get_current_win() is 1008
[ 23:50:19:934 ] [ Info  ] [     ft ] real_current_win&apos;s buf is7
[ 23:50:19:953 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:50:19:953 ] [ Info  ] [     ft ] event is Syntax
[ 23:50:19:953 ] [ Info  ] [     ft ] ev.buf is 9
[ 23:50:19:953 ] [ Info  ] [     ft ] nvim_get_current_buf() is 9
[ 23:50:19:953 ] [ Info  ] [     ft ] nvim_get_current_win() is 1008
[ 23:50:19:953 ] [ Info  ] [     ft ] real_current_win&apos;s buf is7
[ 23:50:19:954 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:50:19:954 ] [ Info  ] [     ft ] event is FileType
[ 23:50:19:954 ] [ Info  ] [     ft ] ev.buf is 9
[ 23:50:19:954 ] [ Info  ] [     ft ] nvim_get_current_buf() is 9
[ 23:50:19:954 ] [ Info  ] [     ft ] nvim_get_current_win() is 1008
[ 23:50:19:954 ] [ Info  ] [     ft ] real_current_win&apos;s buf is7
[ 23:50:19:954 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:50:19:954 ] [ Info  ] [     ft ] event is OptionSet
[ 23:50:19:954 ] [ Info  ] [     ft ] ev.buf is 0
[ 23:50:19:954 ] [ Info  ] [     ft ] nvim_get_current_buf() is 9
[ 23:50:19:954 ] [ Info  ] [     ft ] nvim_get_current_win() is 1008
[ 23:50:19:954 ] [ Info  ] [     ft ] real_current_win&apos;s buf is7
[ 23:50:19:954 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:50:19:954 ] [ Info  ] [     ft ] nvim_get_current_buf() is 7
[ 23:50:19:954 ] [ Info  ] [     ft ] nvim_get_current_win() is 1000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

可以看到，在 event 触发 callback 函数内 nvim_get_current_win 和 nvim_get_current_buf 都临时被修改了。

测试一下，不开窗口效果呢？

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;logger&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ft&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_buf() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_win() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-----------------------------------------------------&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;real_current_win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newbuf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;events&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getcompletion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;event&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endswith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Cmd&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
		&lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test_ft&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-----------------------------------------------------&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;event is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ev.buf is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_buf() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_win() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;real_current_win&apos;s buf is&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_get_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;real_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- vim.api.nvim_open_win(newbuf, false, { split = &quot;above&quot; })&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_set_option_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;filetype&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;test123&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newbuf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_del_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-----------------------------------------------------&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_buf() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_win() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ 23:53:49:058 ] [ Info  ] [     ft ] nvim_get_current_buf() is 10
[ 23:53:49:058 ] [ Info  ] [     ft ] nvim_get_current_win() is 1000
[ 23:53:49:058 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:53:49:078 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:53:49:078 ] [ Info  ] [     ft ] event is Syntax
[ 23:53:49:078 ] [ Info  ] [     ft ] ev.buf is 12
[ 23:53:49:078 ] [ Info  ] [     ft ] nvim_get_current_buf() is 12
[ 23:53:49:078 ] [ Info  ] [     ft ] nvim_get_current_win() is 1001
[ 23:53:49:078 ] [ Info  ] [     ft ] real_current_win&apos;s buf is10
[ 23:53:49:079 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:53:49:079 ] [ Info  ] [     ft ] event is FileType
[ 23:53:49:079 ] [ Info  ] [     ft ] ev.buf is 12
[ 23:53:49:079 ] [ Info  ] [     ft ] nvim_get_current_buf() is 12
[ 23:53:49:079 ] [ Info  ] [     ft ] nvim_get_current_win() is 1001
[ 23:53:49:079 ] [ Info  ] [     ft ] real_current_win&apos;s buf is10
[ 23:53:49:079 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:53:49:079 ] [ Info  ] [     ft ] event is OptionSet
[ 23:53:49:079 ] [ Info  ] [     ft ] ev.buf is 0
[ 23:53:49:079 ] [ Info  ] [     ft ] nvim_get_current_buf() is 12
[ 23:53:49:079 ] [ Info  ] [     ft ] nvim_get_current_win() is 1001
[ 23:53:49:079 ] [ Info  ] [     ft ] real_current_win&apos;s buf is10
[ 23:53:49:079 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:53:49:079 ] [ Info  ] [     ft ] nvim_get_current_buf() is 10
[ 23:53:49:079 ] [ Info  ] [     ft ] nvim_get_current_win() is 1000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这窗口 1001 是什么鬼？临时隐藏窗口？

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;logger&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ft&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_buf() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_win() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-----------------------------------------------------&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;real_current_win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newbuf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;events&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getcompletion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;event&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endswith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Cmd&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
		&lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test_ft&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-----------------------------------------------------&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;event is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ev.buf is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_buf() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_win() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;win count is &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;winnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;winconfig is &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inspect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_get_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())))&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;real_current_win&apos;s buf is&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_get_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;real_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- vim.api.nvim_open_win(newbuf, false, { split = &quot;above&quot; })&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_set_option_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;filetype&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;test123&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newbuf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_del_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-----------------------------------------------------&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_buf() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim_get_current_win() is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_current_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ 23:57:49:249 ] [ Info  ] [     ft ] nvim_get_current_buf() is 9
[ 23:57:49:249 ] [ Info  ] [     ft ] nvim_get_current_win() is 1000
[ 23:57:49:249 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:57:49:268 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:57:49:268 ] [ Info  ] [     ft ] event is Syntax
[ 23:57:49:268 ] [ Info  ] [     ft ] ev.buf is 13
[ 23:57:49:268 ] [ Info  ] [     ft ] nvim_get_current_buf() is 13
[ 23:57:49:268 ] [ Info  ] [     ft ] nvim_get_current_win() is 1001
[ 23:57:49:268 ] [ Info  ] [     ft ] win count is 2
[ 23:57:49:268 ] [ Info  ] [     ft ] winconfig is {
  anchor = &quot;NW&quot;,
  col = 0,
  external = false,
  focusable = false,
  height = 5,
  hide = false,
  mouse = false,
  relative = &quot;editor&quot;,
  row = 0,
  width = 168,
  zindex = 50
}
[ 23:57:49:268 ] [ Info  ] [     ft ] real_current_win&apos;s buf is9
[ 23:57:49:269 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:57:49:269 ] [ Info  ] [     ft ] event is FileType
[ 23:57:49:269 ] [ Info  ] [     ft ] ev.buf is 13
[ 23:57:49:269 ] [ Info  ] [     ft ] nvim_get_current_buf() is 13
[ 23:57:49:269 ] [ Info  ] [     ft ] nvim_get_current_win() is 1001
[ 23:57:49:269 ] [ Info  ] [     ft ] win count is 2
[ 23:57:49:270 ] [ Info  ] [     ft ] winconfig is {
  anchor = &quot;NW&quot;,
  col = 0,
  external = false,
  focusable = false,
  height = 5,
  hide = false,
  mouse = false,
  relative = &quot;editor&quot;,
  row = 0,
  width = 168,
  zindex = 50
}
[ 23:57:49:270 ] [ Info  ] [     ft ] real_current_win&apos;s buf is9
[ 23:57:49:270 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:57:49:270 ] [ Info  ] [     ft ] event is OptionSet
[ 23:57:49:270 ] [ Info  ] [     ft ] ev.buf is 0
[ 23:57:49:270 ] [ Info  ] [     ft ] nvim_get_current_buf() is 13
[ 23:57:49:270 ] [ Info  ] [     ft ] nvim_get_current_win() is 1001
[ 23:57:49:270 ] [ Info  ] [     ft ] win count is 2
[ 23:57:49:270 ] [ Info  ] [     ft ] winconfig is {
  anchor = &quot;NW&quot;,
  col = 0,
  external = false,
  focusable = false,
  height = 5,
  hide = false,
  mouse = false,
  relative = &quot;editor&quot;,
  row = 0,
  width = 168,
  zindex = 50
}
[ 23:57:49:270 ] [ Info  ] [     ft ] real_current_win&apos;s buf is9
[ 23:57:49:270 ] [ Info  ] [     ft ] -----------------------------------------------------
[ 23:57:49:270 ] [ Info  ] [     ft ] nvim_get_current_buf() is 9
[ 23:57:49:270 ] [ Info  ] [     ft ] nvim_get_current_win() is 1000

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这里说明一下，即便是 nvim_open_win 没有执行，Neovim 也会新建一个 autocmd windows，使用 win_gettype() 函数可以获取值为 “autocmd”。
</description>
        <pubDate>Tue, 23 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/how-to-use-ftplugin-directory/</link>
        <guid isPermaLink="true">https://wsdjeg.net/how-to-use-ftplugin-directory/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>本地化管理 Github secrets</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#安装-githubnvim&quot; id=&quot;markdown-toc-安装-githubnvim&quot;&gt;安装 github.nvim&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#使用-githubnvim-访问仓库-secrts&quot; id=&quot;markdown-toc-使用-githubnvim-访问仓库-secrts&quot;&gt;使用 github.nvim 访问仓库 secrts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

有这样一个需求，要给自己多个 Github 仓库增加多个仓库 secrets，以便于 Action 中使用。
起初我是手动在每个仓库的设置页面逐一复制粘贴来添加的。但是这样效率明显太低，而且容易出错，此外后期若需要修改，
还得要重新操作。

于是我就想着是否可以使用脚本访问 Github API 来更改，查阅了 GitHub secrets API 文档，也找到了相关信息。
这篇文章就是我使用 Neovim 编辑并批量更新 Github 仓库 secrets 的完整方案。

&lt;h2 id=&quot;安装-githubnvim&quot;&gt;安装 github.nvim&lt;/h2&gt;

&lt;a href=&quot;https://github.com/wsdjeg/github.nvim&quot;&gt;github.nvim&lt;/a&gt; 是一个 GitHub REST API 的 Lua 实现，用于在 Neovim 中访问 Github API。
早些年，我使用 Vim Script 写过类似的 Vim 插件 &lt;a href=&quot;https://github.com/wsdjeg/github.vim&quot;&gt;GitHub.vim&lt;/a&gt;，
而 github.nvim 算是 github.vim 的 Lua 重新实现版本，目前也仅仅实现了部分 API，会更具个人使用需要，陆续再实现其他的 API。

可以使用任意 Neovim 插件管理器安装，比如 &lt;a href=&quot;https://github.com/wsdjeg/nvim-plug&quot;&gt;nvim-plug&lt;/a&gt;,

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/github.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当然了，你也可以使用 luarocks 安装：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;luarocks install github.nvim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;使用-githubnvim-访问仓库-secrts&quot;&gt;使用 github.nvim 访问仓库 secrts&lt;/h2&gt;

由于 Github 的 secrts API 访问时，传输的数据都是要使用 libsodium 加密，因此需要安装 libsodium，以及对应的 Lua 模块。
这里记录一下 Windows 下安装这两个工具遇到的坑：

从官网下载 &lt;a href=&quot;https://download.libsodium.org/libsodium/releases/libsodium-1.0.20-stable-msvc.zip&quot;&gt;libsodium-1.0.20-stable-msvc.zip&lt;/a&gt;，解压后，
需要将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libsodium\x64\Release\v143\dynamic&lt;/code&gt; 目录加入到环境变量 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt; 内。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PATH&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;;&apos;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[[D:\Downloads\libsodium-1.0.20-stable-msvc\libsodium\x64\Release\v143\dynamic]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此时再使用 luarocks 安装 luasodium，需要指定 libsodium 的安装目录：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;luarocks install luasodium SODIUM_INCDIR=D:\Downloads\libsodium-1.0.20-stable-msvc\libsodium\include SODIUM_DIR=D:\Downloads\libsodium-1.0.20-stable-msvc\libsodium\x64\Release\v143\dynamic
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果提示安装成功后，在 Neovim 内如果使用以下 Lua 脚本，只有最后一个会报错。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;luasodium_ffi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;luasodium&apos;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- ok&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;luasodium_ffi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;luasodium.ffi&apos;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- uses the FFI API (in a C module) ok&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;luasodium_c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;luasodium.core&apos;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- uses the C API ok&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;luasodium_pureffi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;luasodium.pureffi&apos;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- 失败，因为他使用 `require(&apos;ffi&apos;).load(&apos;sodium&apos;)`, 应该是 libsodium&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

最后一个失败的原因时因为 luasodium 源码文件 lib_loader.lua 中使用了 &lt;a href=&quot;https://github.com/wsdjeg/luasodium/blob/49b2d9fc8e4584cf3cf9fc3334469d588a5269ca/lua/luasodium/_ffi/lib_loader.lua#L26&quot;&gt;require(‘ffi’).load(‘sodium’)&lt;/a&gt;

– 在luasodium 修复之前，可以临时如下操作
– 将 dynamic 目录里面的 libsodium.dll 改名为 sodium.dll

我也给 luasodium 提交了一个 PR 来解决这个问题。

确保上述 libsodium、luasodium、github.nvim 都安装好了之后，就可以使用以下脚本了：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secrts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;DOCKER_API_KEY&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;12jdksjdiiwkdjsskkdj&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;LUAROCKS_API_KEY&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;ijnuhbygvtfcrdxesz&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&apos;picker.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&apos;format.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&apos;tasks.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;repos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secrt&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;secrts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;github.secrets&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update_repository_secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

通过上述脚本，就给批量给自己的 Github 仓库设定 secrets，后期如果 API_KEY 修改了，
只需要修改脚本后再执行一次即可。
</description>
        <pubDate>Thu, 04 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/local-github-secrets/</link>
        <guid isPermaLink="true">https://wsdjeg.net/local-github-secrets/</guid>
        
        <category>github</category>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>发现 Git 仓库中幽灵文件</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#使用-git-ghosts-拓展&quot; id=&quot;markdown-toc-使用-git-ghosts-拓展&quot;&gt;使用 git-ghosts 拓展&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#参考链接&quot; id=&quot;markdown-toc-参考链接&quot;&gt;参考链接&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

在使用 Git 过程中，有时候会遇到这样的情况：某个以前删除的文件，不记得当时删除的 commit message 内容了，
也不记得完整的文件路径，只记得文件部分名称，想要找到是哪一个 commit 删除的，发现比较难。

实际上可以通过下方的命令来时间这一功能，首先使用下面的命令搜索删掉的文件路径包含 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt; 的文件列表：

&lt;div class=&quot;language-ps highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;--diff-filter=D&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;--summary&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rg&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rg&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;src&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果要使用 code-runner.nvim，执行并输出，需要设定 ps 的 runner：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;code-runner&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;lua&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-l&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usestdin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;powershell.exe&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-Command&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usestdin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

快捷键调用 code-runner 输出：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Running] powershell.exe -Command - STDIN

--------------------
 delete mode 100644 src/test/hello.c
 delete mode 100644 src/example/delete.c

[Done] exited with code=0, single=0 in 0.916431 seconds
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

获取到上述文件列表后，通过 git.nvim 执行以下命令，就可以打开 log 列表，列表内回车会分屏展示 commit diff。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:Git log -1 -- src/test/hello.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;使用-git-ghosts-拓展&quot;&gt;使用 git-ghosts 拓展&lt;/h2&gt;

最近，给 git.nvim 增加了一个 git-ghosts 的 picker.nvim 拓展。其实现的原理就是参考上述的命令执行顺序。
先获取已删除文件的列表，回车获取改文件的最后一次 commit 的哈希值，然后执行：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:Git show &amp;lt;commit_hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;参考链接&quot;&gt;参考链接&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;https://www.linux88.com/restore-a-deleted-document-in-git/&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 29 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/find-ghosts-file-in-git-repository/</link>
        <guid isPermaLink="true">https://wsdjeg.net/find-ghosts-file-in-git-repository/</guid>
        
        <category>git</category>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 中使用 luarocks</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#安装-luarocks&quot; id=&quot;markdown-toc-安装-luarocks&quot;&gt;安装 luarocks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#在-neovim-内使用-luarocks&quot; id=&quot;markdown-toc-在-neovim-内使用-luarocks&quot;&gt;在 Neovim 内使用 luarocks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#使用-nvim-plug-下载-rocks&quot; id=&quot;markdown-toc-使用-nvim-plug-下载-rocks&quot;&gt;使用 nvim-plug 下载 rocks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#luarocks-的限制&quot; id=&quot;markdown-toc-luarocks-的限制&quot;&gt;luarocks 的限制&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#将插件发布到-luarocks&quot; id=&quot;markdown-toc-将插件发布到-luarocks&quot;&gt;将插件发布到 LuaRocks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#模块载入问题&quot; id=&quot;markdown-toc-模块载入问题&quot;&gt;模块载入问题&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#排除问题&quot; id=&quot;markdown-toc-排除问题&quot;&gt;排除问题&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#neovim-终端中使用&quot; id=&quot;markdown-toc-neovim-终端中使用&quot;&gt;Neovim 终端中使用&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

luarocks 是 lua 常用的包管理器，类似于 python 的 pip。前面使用 Lua 实现了一个 Neovim 的插件管理器，而目前我自己正在维护的插件也都是使用 Lua 来实现的。
因此使用 luarocks 来管理插件，同时又让插件管理器 nvim-plug 支持 luarocks 就显得很有必要了。看了下目前主流的插件管理器 lazy.nvim、rocks.nvim 也是支持 luarcoks 的。

&lt;h2 id=&quot;安装-luarocks&quot;&gt;安装 luarocks&lt;/h2&gt;

在 Windows 下可以使用 scoop 命令进行安装：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scoop install luarocks
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这里需要注意一下，上述命令会自动安装 lua 5.4，但是 Neovim 内默认使用的是 luajit 兼容的 lua 5.1。因此为了避免下载的 rocks 不兼容。可以再执行以下命令：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scoop uninstall lua
scoop install lua51
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

安装完成后检查一下：

&lt;div class=&quot;language-ps highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;luarocks&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rg&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;deploy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

输出内容：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;deploy_bin_dir = &quot;D:\\Scoop\\apps\\luarocks\\current\\rocks\\bin&quot;
deploy_lib_dir = &quot;D:\\Scoop\\apps\\luarocks\\current\\rocks\\lib\\lua\\5.1&quot;
deploy_lua_dir = &quot;D:\\Scoop\\apps\\luarocks\\current\\rocks\\share\\lua\\5.1&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;在-neovim-内使用-luarocks&quot;&gt;在 Neovim 内使用 luarocks&lt;/h2&gt;

在 Neovim 内使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:lua&lt;/code&gt; 命令或者使用 lua 开发 Neovim 插件时，
若想要使用 luarocks 安装的包，其原理就是将 luarocks 所安装的包位置加入到
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.path&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.cpath&lt;/code&gt;：

nvim-plug 中实现这一步骤的逻辑如下：

&lt;a href=&quot;https://github.com/wsdjeg/nvim-plug/blob/edef4e43bd0630a76315fdd69e9bfb49f8fb5a9e/lua/plug/rocks/init.lua#L52&quot;&gt;lua/plug/rocks/init.lua&lt;/a&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enabled&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pcall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;luarocks_config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;luarocks&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;config&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;--json&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}):&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;package.path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;package.path&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;;&apos;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;luarocks_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deploy_lua_dir&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[[\?.lua]]&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;;&apos;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;luarocks_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deploy_lua_dir&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[[\?\init.lua]]&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;;&apos;&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;package.cpath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;package.cpath&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;;&apos;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;luarocks_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deploy_lib_dir&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;?.&apos;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;luarocks_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;external_lib_extension&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;-- 此处，还可以将 luarcoks bin 目录加入到 PATH&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;luarocks_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deploy_bin_dir&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;enabled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;使用-nvim-plug-下载-rocks&quot;&gt;使用 nvim-plug 下载 rocks&lt;/h2&gt;

可以在添加插件时，指定 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type = &apos;rocks&apos;&lt;/code&gt;，比如：

&lt;a href=&quot;https://github.com/wsdjeg/nvim-config/blob/863ab18f3e9ab0ef009387f2c7ce8224cce7bb9e/plugins/mru.lua#L1&quot;&gt;plugins/mru.lua&lt;/a&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/mru.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;events&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;UIEnter&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;enable_cache&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ignore_path_regexs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&apos;/.git/&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&apos;/nvim/runtime/doc/&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&apos;.mp3$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&apos;.mp4$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&apos;.png$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&apos;.jpg$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&apos;.exe$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&apos;nvim-mru.json$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&apos;tags$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;enable_logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sort_by&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;lastenter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;rocks&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;mru(most recently used) files&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

参考以上方式添加插件后，nvim-plug 在安装插件时会自动调用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;luarocks install plugin_name&lt;/code&gt; 这一命令。

&lt;h2 id=&quot;luarocks-的限制&quot;&gt;luarocks 的限制&lt;/h2&gt;

在实现完上述功能后，才发现 luarocks 这个包管理器似乎还有一些限制。比如：

&lt;ol&gt;
  &lt;li&gt;
    不支持同时安装多个插件。

    因为 nvim-plug 是使用异步 job 调用外部命令的，因此支持多线程。
但是起初实现后发现，当同时执行多个 luarocks install 命令时，
只有第一个是成功的，后续的命令都有会报这一错误：&lt;a href=&quot;https://github.com/wsdjeg/nvim-config/blob/863ab18f3e9ab0ef009387f2c7ce8224cce7bb9e/plugins/mru.lua#L1&quot;&gt;Error: command ‘install’ requires exclusive write access&lt;/a&gt;。

    解决的办法是为 luarocks 实现单独的 tasks 序列，逐一执行，这样的话插件的安装会非常慢。一个是单线程，一个是 &lt;a href=&quot;https://github.com/wsdjeg/nvim-config/blob/863ab18f3e9ab0ef009387f2c7ce8224cce7bb9e/lua/plugins.lua#L28&quot;&gt;16 线程 (max_processes = 16)&lt;/a&gt;。
  &lt;/li&gt;
  &lt;li&gt;
    无法根据 plugSpec 获取的 rtp 目录位置

    一个最简单 plugSpec 比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{ &apos;wsdjeg/mru.nvim&apos; }&lt;/code&gt;，
默认 type 是 git，我是可以获取到该插件默认的 runtimepath 值为
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plug.config.bundle_dir .. &apos;/&apos; .. &apos;wsdjeg/mru.nvim&apos;&lt;/code&gt;，
此时就可以根据这个目录是否存在来判断插件是否已安装。

    但是，这样一个 plugSpec：

    &lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/mru.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;rocks&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    将无法获取到默认的 runtimepath 目录位置，因为他的格式是

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;D:/Scoop/apps/luarocks/current/rocks/lib/luarocks/rocks-5.1/mru.nvim/1.4.0-1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    最后面这个版本号，除非是 plugSpec 内指定，否则是无法判断到默认的值的。

    最终的解决方案是&lt;a href=&quot;https://github.com/wsdjeg/nvim-plug/blob/edef4e43bd0630a76315fdd69e9bfb49f8fb5a9e/lua/plug/rocks/init.lua#L5&quot;&gt;分析 luarocks list 命令的输出内容&lt;/a&gt;，返回一个类似与这样的 lua table：

    &lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;mru.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rtp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;D:/Scoop/apps/luarocks/current/rocks/lib/luarocks/rocks-5.1/mru.nvim/1.4.0-1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;rooter.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rtp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;D:/Scoop/apps/luarocks/current/rocks/lib/luarocks/rocks-5.1/rooter.nvim/1.3.0-1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;将插件发布到-luarocks&quot;&gt;将插件发布到 LuaRocks&lt;/h2&gt;

这里主要使用到两个 Github actions：

&lt;ul&gt;
  &lt;li&gt;googleapis/release-please-action&lt;/li&gt;
  &lt;li&gt;nvim-neorocks/luarocks-tag-release&lt;/li&gt;
&lt;/ul&gt;

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;googleapis/release-please-action&lt;/code&gt; 来自动打 tag 并且新建 GitHub release，可以参考之前的文章&lt;a href=&quot;../release-please-action/&quot;&gt;《Github 仓库自动 release》&lt;/a&gt;。

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim-neorocks/luarocks-tag-release&lt;/code&gt; GitHub action 自动将 tag 上传到 luarocks.org。

在仓库根目录新建文件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.github/workflows/luarocks.yml&lt;/code&gt;:

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Push to Luarocks&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Will upload to luarocks.org when a tag is pushed&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;*&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;pull_request&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Will test a local install without uploading to luarocks.org&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;workflow_dispatch&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;luarocks-upload&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;runs-on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ubuntu-22.04&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;LuaRocks Upload&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nvim-neorocks/luarocks-tag-release@v7&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;LUAROCKS_API_KEY&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

存在一个问题，luarocks-tag-release 使用 copy_directories 来复制打包插件的其他文件，
但是 luarocks 一旦使用了 copy_directories 这一设置，就不会复制默认的 doc 文件了。

相关 issue ： &lt;a href=&quot;https://github.com/luarocks/luarocks/issues/1266&quot;&gt;luarocks/issues/1266&lt;/a&gt;

代码逻辑 &lt;a href=&quot;https://github.com/luarocks/luarocks/blob/498a26568eb0ea6dd585bf9f87558e4a0e48387a/src/luarocks/build.lua#L344-L363&quot;&gt;src/luarocks/build.lua#L344-L363&lt;/a&gt;

&lt;h2 id=&quot;模块载入问题&quot;&gt;模块载入问题&lt;/h2&gt;

neovim 中直接使用 rocks 似乎还有问题，dll 文件载入时会报错，估计跟 luarocks 的包编译方式有关

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;D:\wsdjeg\my-blog&amp;gt;luarocks list | rg file -A 2
luafilesystem
   1.8.0-1 (installed) - D:\Scoop\apps\luarocks\current\rocks\lib\luarocks\rocks-5.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

然后在 Neovim 内执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:lua require(&apos;lfs&apos;)&lt;/code&gt; 时，报错：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;E5108: Error executing lua error loading module &apos;lfs&apos; from file &apos;D:\Scoop\apps\luarocks\current\rocks\lib\lua\5.1\lfs.dll&apos;:
        找不到指定的模块。

stack traceback:
        [C]: at 0x7ff83ac1bdb0
        [C]: in function &apos;require&apos;
        [string &quot;:lua&quot;]:1: in main chunk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

实际上这个 dll 文件是存在的：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
D:\Scoop\apps\luarocks\current\rocks\lib\lua\5.1&amp;gt;ls
lfs.dll
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;排除问题&quot;&gt;排除问题&lt;/h2&gt;

使用 scoop 安装 &lt;a href=&quot;https://github.com/lucasg/Dependencies&quot;&gt;dependencies&lt;/a&gt;,

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scoop install dependencies
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

打开 lfs.dll 文件，发现确实是依赖问题：

&lt;img src=&quot;../images/luarocks-lfs-error.png&quot; alt=&quot;lfs.dll&quot; /&gt;

在 lua51 的安装目录里：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;D:\Scoop\apps\lua51\current&amp;gt;ls
Microsoft.VC80.CRT  install.json  lua5.1.dll.manifest  lua51.dll           manifest.json
bin2c5.1.exe        liblua5.1.a   lua5.1.exe           lua51.dll.manifest  wlua5.1.exe
include             lua5.1.dll    lua5.1.exe.manifest  luac5.1.exe         wlua5.1.exe.manifest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

而 Neovim 中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:lua&lt;/code&gt; 调用的是：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;D:\Scoop\apps\neovim\current\bin&amp;gt;ls
dbghelp.dll  lua51.dll  nvim.exe  platforms  win32yank.exe  xxd.exe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

使用 scoop 安装 luajit：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scoop install luajit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

看下 luajit 的目录结构

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;D:\Scoop\apps\luajit/..
  2.1.1762795099-1
  current ➛ 2.1.1762795099-1
    bin
       lua51.dll
       luajit
       luajit-2.1.1762795099.exe
       luajit.exe
    include/luajit-2.1
       lauxlib.h
       lua.h
       lua.hpp
       luaconf.h
       luajit.h
       lualib.h
    lib
    share
     install.json
     manifest.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;D:\Scoop\apps\luarocks\current\config.lua&lt;/code&gt; 为：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;lua_interpreter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;D:/Scoop/apps/luajit/current/bin/luajit.exe&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;lua_version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;5.1&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rocks_trees&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;s2&quot;&gt;&quot;D:/Scoop/apps/luarocks/current/rocks&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;variables&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;LUA&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;D:/Scoop/apps/luajit/current/bin/luajit.exe&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;LUA_BINDIR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;D:/Scoop/apps/luajit/current/bin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;LUA_INCDIR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;D:/Scoop/apps/luajit/current/include/luajit-2.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;LUA_DIR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;D:/Scoop/apps/luajit/current/bin&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

重新安装 luafilesystem：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;luarocks install luafilesystem --force
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此时再使用 Dependencies 查看 lfs.dll：

&lt;img src=&quot;../images/luarocks-lfs-ok.png&quot; alt=&quot;lfs-ok&quot; /&gt;

此时在 Neovim 中执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:=require(&apos;lfs&apos;)&lt;/code&gt; 就会看到：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
  _COPYRIGHT = &quot;Copyright (C) 2003-2017 Kepler Project&quot;,
  _DESCRIPTION = &quot;LuaFileSystem is a Lua library developed to complement the set of functions related to file systems offered by the standard Lua distribution&quot;,
  _VERSION = &quot;LuaFileSystem 1.8.0&quot;,
  attributes = &amp;lt;function 1&amp;gt;,
  chdir = &amp;lt;function 2&amp;gt;,
  currentdir = &amp;lt;function 3&amp;gt;,
  dir = &amp;lt;function 4&amp;gt;,
  link = &amp;lt;function 5&amp;gt;,
  lock = &amp;lt;function 6&amp;gt;,
  lock_dir = &amp;lt;function 7&amp;gt;,
  mkdir = &amp;lt;function 8&amp;gt;,
  rmdir = &amp;lt;function 9&amp;gt;,
  setmode = &amp;lt;function 10&amp;gt;,
  symlinkattributes = &amp;lt;function 11&amp;gt;,
  touch = &amp;lt;function 12&amp;gt;,
  unlock = &amp;lt;function 13&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;neovim-终端中使用&quot;&gt;Neovim 终端中使用&lt;/h2&gt;

为了能在 Neovim 内置终端中使用 lua，luajit，luarocks 等，给 nvim-plug 增加这样一个 patch：

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gh&quot;&gt;diff --git a/lua/plug/rocks/init.lua b/lua/plug/rocks/init.lua
index e336791..58f391d 100644
&lt;/span&gt;&lt;span class=&quot;gd&quot;&gt;--- a/lua/plug/rocks/init.lua
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/lua/plug/rocks/init.lua
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -71,6 +71,8 @@&lt;/span&gt; function M.enable()
             .. luarocks_config.deploy_lib_dir
             .. &apos;\\?.&apos;
             .. luarocks_config.external_lib_extension
&lt;span class=&quot;gi&quot;&gt;+        vim.env.LUA_PATH = package.path
+        vim.env.LUA_CPATH = package.cpath
&lt;/span&gt;     end)
     if ok then
         enabled = true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这样在 Neovim 内置终端内使用 lua 命令，或者 luajit 命令，就会自动读取这两个变量值。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;D:\wsdjeg\my-blog&amp;gt;lua
Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
&amp;gt; print(require(&apos;lfs&apos;))
table: 00000000004DCAC0
&amp;gt; 

D:\wsdjeg\my-blog&amp;gt;luajit
LuaJIT 2.1.1762795099 -- Copyright (C) 2005-2025 Mike Pall. https://luajit.org/
JIT: ON SSE3 SSE4.1 BMI2 fold cse dce fwd dse narrow loop abc sink fuse
&amp;gt; print(require(&apos;lfs&apos;))
table: 0x01f72937bc70
&amp;gt; 
D:\wsdjeg\my-blog&amp;gt;echo print(require(&quot;lfs&quot;)) | nvim -l -  
table: 0x01dcba84a148
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Thu, 27 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/using-luarocks-in-neovim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/using-luarocks-in-neovim/</guid>
        
        <category>neovim</category>
        
        <category>lua</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 窗口 API 参数 noautocmd 测试</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;!-- prettier-ignore-end --&gt;

最近在修改 notify.nvim 插件源码的时候有这么一段：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win_config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;-- .....&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_is_valid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_is_valid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;win_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;noautocmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_open_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_set_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

我把 win_config 内容省略了，主要想表达的意思是，
本来我想通过一个固定的窗口配置来打开或者设置窗口的参数。
但是 Neovim 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_open_win&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_win_set_config&lt;/code&gt;
两个函数所接受的 win_opt 选项是有区别的，已存在的窗口使用后者设置时不能够传入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;noautocmd&lt;/code&gt; 选项（&lt;a href=&quot;https://github.com/neovim/neovim/issues/36409&quot;&gt;neovim#36409&lt;/a&gt;）。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&apos;noautocmd&apos; cannot be used with existing windows
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

于是只能分开写，在调用 nvim_open_win 时传入 noautocmd 参数。

那么这个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;noautocmd&lt;/code&gt; 到底禁用了哪些事件，以及禁用的时机时什么呢？

以下为测试脚本：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;logger&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;t_no&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;test_noautocmd&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;WinEnter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BufWinEnter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BufEnter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;WinLeave&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;TextChangedI&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_open_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;split&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;above&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;noautocmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- [ 20:43:20:664 ] [ Info  ] [   t_no ] TextChangedI&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- [ 20:43:23:092 ] [ Info  ] [   t_no ] WinLeave&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- [ 20:43:23:093 ] [ Info  ] [   t_no ] WinEnter&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- [ 20:43:23:094 ] [ Info  ] [   t_no ] BufEnter&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;logger&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;t_no&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;test_noautocmd&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;WinEnter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BufWinEnter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BufEnter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;WinLeave&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;TextChangedI&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_open_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;split&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;above&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;noautocmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- [ 20:44:50:454 ] [ Info  ] [   t_no ] WinLeave&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- [ 20:44:50:455 ] [ Info  ] [   t_no ] WinEnter&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- [ 20:44:50:456 ] [ Info  ] [   t_no ] BufEnter&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- [ 20:44:50:456 ] [ Info  ] [   t_no ] BufWinEnter&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- [ 20:44:51:279 ] [ Info  ] [   t_no ] TextChangedI&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- [ 20:44:52:045 ] [ Info  ] [   t_no ] WinLeave&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- [ 20:44:52:046 ] [ Info  ] [   t_no ] WinEnter&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- [ 20:44:52:048 ] [ Info  ] [   t_no ] BufEnter&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果去看 API 的源码，neovim 这段 nvim_open_win api 的源码。

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Window&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;nvim_open_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Buffer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;win_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;FUNC_API_SINCE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FUNC_API_TEXTLOCK_ALLOW_CMDWIN&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define HAS_KEY_X(d, key) HAS_KEY(d, win_config, key)
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;buf_T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;find_buffer_by_handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmdwin_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmdwin_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;api_set_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kErrorTypeException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;%s&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e_cmdwin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;WinConfig&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WIN_CONFIG_INIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_win_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_split&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HAS_KEY_X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HAS_KEY_X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertical&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Window&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;noautocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;block_autocmds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;win_T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;tabpage_T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curtab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curwin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;win_T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curwin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;find_window_by_handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// find_window_by_handle has already set the error&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_split&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w_floating&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;api_set_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kErrorTypeException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Cannot split a floating window&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win_find_tabpage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;check_split_disallowed_err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curwin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// error already set&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HAS_KEY_X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertical&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HAS_KEY_X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vertical&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p_spr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kWinSplitRight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kWinSplitLeft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p_sb&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kWinSplitBelow&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kWinSplitAbove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win_split_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WSP_NOENTER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WSP_VERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;TRY_WRAP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curwin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win_split_ins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;switchwin_T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;switchwin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// `parent` is valid in `tp`, so switch_win should not fail.&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;switch_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;switchwin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win_split_ins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;restore_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;switchwin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w_config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Without room for the requested size, window sizes may have been equalized instead.&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// If the size differs from what was requested, try to set it again now.&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WSP_VERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w_width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;win_setwidth_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WSP_VERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w_height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;win_setheight_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;check_split_disallowed_err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curwin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// error already set&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win_new_float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ERROR_SET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;api_set_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kErrorTypeException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Failed to create window&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_cmdline_offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INT_MAX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cmdline_win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Autocommands may close `wp` or move it to another tabpage, so update and check `tp` after each&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// event. In each case, `wp` should already be valid in `tp`, so switch_win should not fail.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Also, autocommands may free the `buf` to switch to, so store a bufref to check.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;bufref_T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bufref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_bufref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bufref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;noautocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;switchwin_T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;switchwin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;switch_win_noblock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;switchwin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;apply_autocmds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EVENT_WINNEW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curbuf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;tp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win_find_tabpage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;restore_win_noblock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;switchwin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;goto_tabpage_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win_find_tabpage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bufref_valid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bufref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w_buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// win_set_buf temporarily makes `wp` the curwin to set the buffer.&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// If not entering `wp`, block Enter and Leave events. (cringe)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;au_no_enter_leave&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curwin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;noautocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;au_no_enter_leave&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;autocmd_no_enter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;autocmd_no_leave&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;win_set_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;noautocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;tp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win_find_tabpage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;au_no_enter_leave&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;autocmd_no_enter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;autocmd_no_leave&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;api_set_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kErrorTypeException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Window was closed immediately&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kWinStyleMinimal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;win_set_minimal_style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;didset_window_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;rv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fconfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;noautocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;unblock_autocmds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#undef HAS_KEY_X
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

从源码中不难看出，这个 noautocmd 选项只是在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_open_win&lt;/code&gt; 这个函数调用内起作用，在最后的时候使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unblock_autocmds&lt;/code&gt; 又恢复的事件的响应。
</description>
        <pubDate>Wed, 12 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-nvim-win-noautocmd/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-nvim-win-noautocmd/</guid>
        
        <category>neovim</category>
        
        <category>lua</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 模糊搜索插件 picker.nvim</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#安装和配置&quot; id=&quot;markdown-toc-安装和配置&quot;&gt;安装和配置&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#基本使用&quot; id=&quot;markdown-toc-基本使用&quot;&gt;基本使用&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#内置-source&quot; id=&quot;markdown-toc-内置-source&quot;&gt;内置 source&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#其他插件-source&quot; id=&quot;markdown-toc-其他插件-source&quot;&gt;其他插件 source&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#如何自定义拓展&quot; id=&quot;markdown-toc-如何自定义拓展&quot;&gt;如何自定义拓展&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

模糊搜索插件（fuzzy finder）算是日常使用 Neovim 必不可少的插件之一。早期我在使用 Vim 时，最开始使用过 ctrlp.vim、unite.vim、leaderf、以及后来切换到的 denite.vim。
因为一直是在 Windows 系统下居多，因此没使用 fzf 系列的插件，最开始的时候 Windows 默认终端支持这些命令可不是那么的友好。因此我更倾向于使用 Vim 内置窗口实现的这类插件。

随着 Neovim 的浮窗功能完善，使用浮窗实现的 telescope.nvim 是我日常主要使用的工具了，我自己也实现了好一些 telescope extensions。
但是 telescope 似乎太复杂了，而且个人感觉维护也变得不是那么的活跃了，因此就自己写了一个 &lt;a href=&quot;https://github.com/wsdjeg/picker.nvim&quot;&gt;picker.nvim&lt;/a&gt;

&lt;h2 id=&quot;安装和配置&quot;&gt;安装和配置&lt;/h2&gt;

picker.nvim 的安装很简单，默认是没有任何仓库依赖，可以使用任意插件管理器进行安装，比如 &lt;a href=&quot;https://github.com/wsdjeg/nvim-plug&quot;&gt;nvim-plug&lt;/a&gt;：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/picker.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;picker&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;ignorecase&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- ignorecase (boolean): defaults to false&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- set picker screen width, default is 0.8 * vim.o.columns&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;current_icon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;current_icon_hl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;CursorLine&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;enable_preview&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;preview_timeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;highlight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;matched&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Tag&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;prompt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;position&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;bottom&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- set prompt position, bottom or top&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;icon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;icon_hl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Error&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;insert_timeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- display/hide source name&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mappings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;Esc&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;next_item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;Tab&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;previous_item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;S-Tab&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;open_item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;Enter&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;toggle_preview&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;C-p&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上是插件初始化时，默认的配置，也可以参考我的配置文件：&lt;a href=&quot;https://github.com/wsdjeg/nvim-config/blob/17118bc0731d40f3e65827e23e05635ef1d7ac2b/plugins/picker.lua#L1&quot;&gt;nvim-config/plugins/picker.lua&lt;/a&gt;, 在我的配置里，我使用 picker.nvim 接管了 Neovim 默认的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.ui.select&lt;/code&gt; 函数。

&lt;h2 id=&quot;基本使用&quot;&gt;基本使用&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Picker&lt;/code&gt; 命令看看目前支持的源（sources）&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Picker source_name&lt;/code&gt; 指定打开某个源进行匹配搜索。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--input&lt;/code&gt; 指定默认初始化输入的内容&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--input=&amp;lt;cword&amp;gt;&lt;/code&gt; 指定以光标下的词作为默认输入内容。&lt;/li&gt;
&lt;/ol&gt;

默认只有四个快捷键，可以在 setup 时指定，默认是以下四个按键：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;key binding&lt;/th&gt;
      &lt;th&gt;description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tab&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;next item&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S-Tab&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;previous item&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enter&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;default action&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Esc&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;close picker&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

其他的快捷键通过 source 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;action()&lt;/code&gt; 函数返回定义。

&lt;h2 id=&quot;内置-source&quot;&gt;内置 source&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;source&lt;/th&gt;
      &lt;th&gt;description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;buffers&lt;/td&gt;
      &lt;td&gt;listed buffers&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;buftags&lt;/td&gt;
      &lt;td&gt;ctags outline for current buffer&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;cmd_history&lt;/td&gt;
      &lt;td&gt;results from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:history :&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;colorscheme&lt;/td&gt;
      &lt;td&gt;all colorschemes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;files&lt;/td&gt;
      &lt;td&gt;files in current dir&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;help_tags&lt;/td&gt;
      &lt;td&gt;neovim help tags source&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;highlights&lt;/td&gt;
      &lt;td&gt;highlight group source&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;jumps&lt;/td&gt;
      &lt;td&gt;jump list&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;lines&lt;/td&gt;
      &lt;td&gt;lines in current buffer&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;loclist&lt;/td&gt;
      &lt;td&gt;location list source&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;lsp_document_symbols&lt;/td&gt;
      &lt;td&gt;document symbols result from lsp client&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;lsp_references&lt;/td&gt;
      &lt;td&gt;lsp references&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;lsp_workspace_symbols&lt;/td&gt;
      &lt;td&gt;workspace symbols&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;marks&lt;/td&gt;
      &lt;td&gt;marks list&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;picker_config&lt;/td&gt;
      &lt;td&gt;picker config source&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;qflist&lt;/td&gt;
      &lt;td&gt;quickfix source&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;registers&lt;/td&gt;
      &lt;td&gt;registers context&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;其他插件-source&quot;&gt;其他插件 source&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;source&lt;/th&gt;
      &lt;th&gt;description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;mru&lt;/td&gt;
      &lt;td&gt;most recent used files, need &lt;a href=&quot;https://github.com/wsdjeg/mru.nvim&quot;&gt;mru.nvim&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;project&lt;/td&gt;
      &lt;td&gt;project history, need &lt;a href=&quot;https://github.com/wsdjeg/rooter.nvim&quot;&gt;rooter.nvim&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;bookmarks&lt;/td&gt;
      &lt;td&gt;all bookmarks, need &lt;a href=&quot;https://github.com/wsdjeg/bookmarks.nvim&quot;&gt;bookmarks.nvim&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;zettelkasten&lt;/td&gt;
      &lt;td&gt;zettelkasten notes source from &lt;a href=&quot;https://github.com/wsdjeg/zettelkasten.nvim&quot;&gt;zettelkasten.nvim&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;zettelkasten_tags&lt;/td&gt;
      &lt;td&gt;zettelkasten tags source from &lt;a href=&quot;https://github.com/wsdjeg/zettelkasten.nvim&quot;&gt;zettelkasten.nvim&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;git-branch&lt;/td&gt;
      &lt;td&gt;git branch source from &lt;a href=&quot;https://github.com/wsdjeg/git.nvim&quot;&gt;git.nvim&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;music-player&lt;/td&gt;
      &lt;td&gt;music-player source form &lt;a href=&quot;https://github.com/wsdjeg/music-player.nvim&quot;&gt;music-player.nvim&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;plug&lt;/td&gt;
      &lt;td&gt;plugins source for &lt;a href=&quot;https://github.com/wsdjeg/nvim-plug&quot;&gt;nvim-plug&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;async_files&lt;/td&gt;
      &lt;td&gt;async files source, require &lt;a href=&quot;https://github.com/wsdjeg/job.nvim&quot;&gt;job.nvim&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;如何自定义拓展&quot;&gt;如何自定义拓展&lt;/h2&gt;

picker.nvim 的拓展实际上就是一个 Lua table：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;---@return PickerItem[]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;---@param entry PickerItem&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;default_action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;--- 只有需要使用到预览窗口，才需要定义 preview 函数。&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;preview_win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;preview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Fri, 31 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-fuzzy-finder-picker-nvim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-fuzzy-finder-picker-nvim/</guid>
        
        <category>neovim</category>
        
        <category>lua</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Github 仓库自动 release</title>
        <description>&lt;!-- prettier-ignore-start --&gt;


&lt;!-- prettier-ignore-end --&gt;

因为仓库比较多（&lt;del&gt;比较懒&lt;/del&gt;），不想每次都手动发布版本，写项目版本更新的内容，因此给自己的每一个仓库引入了 &lt;a href=&quot;https://github.com/googleapis/release-please-action&quot;&gt;googleapis/release-please-action&lt;/a&gt;

在仓库的根目录新建文件：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.github/workflows/release-please.yml&lt;/code&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;branches&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;master&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;permissions&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;issues&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;write&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;write&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;pull-requests&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;write&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;release-please&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;release-please&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;runs-on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;googleapis/release-please-action@v4&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# this assumes that you have created a personal access token&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# (PAT) and configured it as a GitHub action secret named&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# `MY_RELEASE_PLEASE_TOKEN` (this secret name is not important).&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# this is a built-in strategy in release-please, see &quot;Action Inputs&quot;&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# for more options&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;release-type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;simple&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

然后，给仓库的 Github Action 添加权限，勾选 “Allow GitHub Actions to create and approve pull requests”，在仓库的 Settings &amp;gt; Actions &amp;gt; General。

完成以上步骤以后，书写 Git commit 时，需要遵循 &lt;a href=&quot;https://www.conventionalcommits.org/en/v1.0.0/&quot;&gt;Conventional Commits&lt;/a&gt;。
</description>
        <pubDate>Mon, 22 Sep 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/release-please-action/</link>
        <guid isPermaLink="true">https://wsdjeg.net/release-please-action/</guid>
        
        <category>git</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>为什么有那么多人讨厌清朝？</title>
        <description>最近有点犯书荒，在搜索历史类小说的时候发现隋、唐、宋、明等朝代的小说较多，相关影视剧也是这样。相反元、清朝代的就非常少，
记得还是上学期间有一些清朝宫廷剧，往后几乎很少看到。

可能在汉人的眼里，清朝实际上是侵略者统治的朝代，和日本当年类似。不同的是现在的中国是满族也在期内而且人口还不少。为了民族统一，国务院甚至&lt;a href=&quot;https://www.neac.gov.cn/seac/zcfg/201208/1074206.shtml&quot;&gt;发文禁止使用满清一词&lt;/a&gt;。

知乎上有这样一个问题，为什么有那么多人讨厌清朝？其中&lt;a href=&quot;https://www.zhihu.com/question/315051796/answer/1582945388&quot;&gt;一个答案&lt;/a&gt;中提到了很多满清犯下恶。

&lt;blockquote&gt;
  畿南之屠、潼关之屠、扬州十日、嘉定三屠、昆山之屠、嘉兴之屠、江阴八十一日、常熟之屠、四川之屠、金华之屠、南昌之屠、湘潭之屠、南雄之屠、汾州之屠、大同之屠、广州之屠、潮州之屠。凡此种种，皆为历史记载有据可查之大屠也。
&lt;/blockquote&gt;

1644年，是中国历史上天翻地覆的一年，就在这一年清军入主中原，无数汉人的噩梦就此开始。清军入住中原后，强迫汉人剃发易服

，这对于汉人来说以一种莫大的侮辱，各地人民纷纷起义反抗清朝，清朝对此采取屠城政策来强行推行“剃发易服”政策，于是乎一场场惨无人道大屠杀在中华大地上轮番上演。

1.畿南之屠
清朝的建立，源于一场惨绝人寰的大屠杀，清军入关就是外族入侵，为了巩固自己的地位与文化，就通过杀戮屠城的方式威慑全国，清军入关前后不断的屠杀汉人，前后屠虐了一百多年，死亡人数在四千万至八千万之间，史称为满清大屠杀。

顺治元年
(1644年)五月，清朝睿亲王多尔衮

在北直隶三河、昌平、良乡等地进行的屠城，五千人被残杀。

2.潼关之屠
明崇祯十七年（公元1644年正月十三日）满清“豫亲王”爱新觉罗多铎在陕西潼关进行惨绝人寰的大规模屠城，手无寸铁的士兵被多铎尽数屠杀，清军并大肆屠城，7000汉人被清军杀死，在历史上有一句对这件事的说法“潼关之屠七千“（就是屠夫多铎在潼关杀害那么多无辜的汉人）

顺治元年(1644年)正月十三日，清朝“豫亲王”多铎在陕西潼关地进行的屠城，七千人被残杀。

3.扬州十日
清军入关之后，满族人为了统治中国，就对汉人颁布了毫无人性的剃发令、文字狱，以及各个城镇的威慑屠杀，最惨绝人寰的要数“扬州十日”以及“嘉定三屠”，其中扬州十日是最为惨痛的，清军破城后整整屠杀了十天，被屠杀的汉人达到了80万，要比南京大屠杀多50万人。

顺治二年、南明弘光元年(1645年5月20日)。清军攻破扬州，开始屠杀城内的平民百姓。史载：“诸妇女长索系颈，累累如贯珠，一步一跌，遍身泥土;满地皆婴儿，或衬马蹄，或藉人足，肝脑涂地，泣声盈野。”“初四日，天始霁。道路积尸既经积雨暴涨，而青皮如蒙鼓，血肉内溃。秽臭逼人，复经日炙，其气愈甚。前后左右，处处焚灼。室中氤氲，结成如雾，腥闻百里。”后来由城内僧人收殓的尸体就超过了八十万具。

4.嘉定三屠
“嘉定三屠”是指一场大屠杀，一场灭绝人性的全副武装的清兵对手无寸铁的汉人进行的屠杀，清朝顺治二年时清军攻破嘉定，并颁布剃发令但是当地的百姓违抗命令拒绝剃发，此事激怒了清军于是下令屠城屠城的命令，共下达了三次，屠城进行了三回，所以称“三屠”，而死亡人数更是达到了10万之众。

顺治二年、南明弘光元年(1645年)在清军攻破嘉定后，清军将领李成栋三次下令对城中平民进行大屠杀。在屠城过程中，城中百姓或者悬梁自杀或者投井和跳河，被砍断手和脚的百姓在地上挣扎着。清军将一大部分逃生的百姓赶到河边，然后将他们赶进河中纷纷淹死，河里的水都不能流动了。

5.昆山之屠

顺治二年、南明弘光元年(1645年)昆山县人民杀该县清委知县阎茂才，起兵反清。七月初六，清军破城，随即屠城，士民死难者达数万人。清军屠昆山的时候，有妇女千人藏匿在昆山顶上。有个小孩忍不住哭出声来，被清军发现，于是大肆屠杀这些妇女。

6.嘉兴之屠

顺治二年、南明弘光元年(1645年)闰六月二十六日，浙江布政使司隶嘉兴府为反抗清军暴行，嘉兴民众揭竿而起，乡的明翰林学士屠象美、明兵科给事中李毓新主其事，时降清的明嘉兴总兵陈梧反时任大将军指挥义师，前吏部郎中钱棅助饷。二十六日城陷，逃不出的居民除大批年轻妇女被清军掳掠和一些僧人幸免外，几乎全遭屠杀。按当时人口来推，可能约五十万余人遇难。

7.江阴八十一日

顺治二年、南明弘光元年(1645年)清朝颁布剃发令后，江阴人民举行了反清起义，进行反清斗争。清廷先后调动24万军队攻城，江阴人民浴血奋战，守城八十一天，击毙清三王十八将，清军死伤过十万。但终因力量悬殊，粮食罄尽，守城者全部壮烈牺牲。城破后遭到清军血腥屠杀，繁华的街市尽为废墟。

8.四川大屠杀

从顺治三年(1646年)至康熙初期，清军开始侵入四川，在四川各地进行大屠杀。顺治四年(1647年)多尔衮、孝庄采取了彻底屠杀的办法作为报复，公开发布告示，宣称：民贼相混，玉石难分，或屠全城，或屠男而留女。前后十多年里共有500多万人被清军屠杀。

9.常熟之屠

顺治二年、南明弘光元年(1645年)八月到九月，清军先后占领苏州和南直隶常熟之后的纵兵焚烧杀掠。在常熟大屠杀中被屠杀的百姓无法计算，沿河沿岸都是人头。

10.金华之屠

顺治三年、南明隆武二年(1646年)七月十六日，清朝“贝勒”博洛在攻占浙江金华府进行的开始大规模屠城。大约有五万人被屠杀。

11.泾县之屠

顺治三年、南明隆武二年(1646年)八月十七日，清朝“提督”张天禄、“池州总兵”于永绶在南直隶泾县、徽州、绩溪县等地进行的一次大规模屠城。大约有五万人被屠杀。

12.赣州之屠

顺治三年、南明隆武二年(1646年)十月初四日，清朝“江西提督”金声桓、“总兵”柯永盛在江西赣州府进行的一次大规模屠城。大约有二十万人被屠杀。

13.同安之屠

顺治四年(1647年)清军攻克福建厦门和同安县，然后屠城。福建同安县屠城死难5万余人，梵天寺住持无疑和尚收尸合葬于寺东北一里之地，建亭“无祠亭”，墓碑上则刻“万善同归所”。

14.平海之屠

顺治四年、南明永历元年(1647年)七月，清军在福建平海卫进行大规模屠城。被屠杀的无辜百姓具体人数不详。

15.南昌之屠

顺治五年(1648年)清军包围南昌。次年三月间，南昌城陷，清军屠城。八旗军把从南昌掠来的妇女分给各营，昼夜不停的轮奸。不久之后南昌被起义军夺了回来，但在顺治六年(1649年)清军再次占领江西南昌，下令进行屠杀。

16.邵武之屠

顺治五年、南明永历二年(1648年)五月，清朝“福建左路总兵”王之纲在福建邵武县进行屠城，被屠杀的无辜百姓人数不详。

17.湘潭之屠

顺治六年(1649年)正月二十一日清军攻入湖南湘潭和沅州(今芷江)，南明督师何腾蛟被俘。清郑亲王济尔哈朗下令在湘潭屠城，湘潭城中百姓几乎全被杀光，城中不满百人。

18.同安之屠

顺治五年、南明永历二年(1648年)八月十六日，清朝“靖南将军”陈泰、“浙闽总督”陈锦、“福建提督”赵国祚在福建同安县进行大屠杀，大约有五万人被屠杀。

19.南雄之屠

顺治六年(1649年)农历十二月二十九日，清军抵达南雄，年三十除夕晚上清军放火焚烧鼓楼，趁明军慌乱救火之际，攻入城内。对南雄县民大肆屠杀，“大清平、靖二藩克雄城，民尽屠戮，十存二三。

20.信丰之屠

顺治六年、南明永历三年(1649年)三月初一日，清朝“梅勒章京”胶商攻克广东信丰县，进行大规模屠城。

21.蒲城之屠

顺治六年、南明永历三年(1649年)四月初五日，清朝“固山额真”李国翰攻克陕西蒲城县然后进行大规模屠城。大约有一万人被屠杀。

22.曹州之屠

顺治六年、南明永历三年(1649年)十月初四日，清朝梅勒章京赖恼、沂州总兵佟养量、临清总兵宜永贵等攻克山东州曹州，进行屠城。被屠杀的无辜居民人数不详。

23.汾州之屠

顺治六年、南明永历三年(1649年)九月至十一月，清朝“端重亲王”博洛、“和硕亲王”满达海等在山西汾州、太谷县、泌州、泽州等地进行规模屠城。大约有四十万人被屠杀。

24.大同之屠

顺治六年(1649年)清军在大同屠杀后，全城只剩下5个重案犯。清朝派来的大同知府，上书顺治帝，称既然没有了苦主，就可以释放这5个人了。这份奏折，至今保存在第一历史档案馆。

25.广州大屠杀

顺治七年(1650年)尚可喜打带领清军清军攻广州，围城十个多月后广州城破。清军入城之后开始屠城，史书记载： ”可喜屠广州，孑遗无留;逸出城者，挤之海中。“ 死难十万至七十万人。

26.潮州之屠

顺治十年(1653年)清军占领广东的潮州和南雄，清军之后进行下令屠杀，“纵兵屠掠，遗骸十余万”，“癸巳，郡城破，横尸遍野……收遗骸十余万，作普同塔于葫芦山”。

揭阳县观音堂海德和尚等收尸聚焚于西湖山，将骨灰葬在西湖南岩。福建同安县屠城死难五万余人，梵天寺主持释无疑收尸合葬于寺东北一里之地，建亭“无祠亭“，墓碑上则刻“万善同归所”。南雄县民也遭到大肆屠杀，“大清平、靖二藩克雄城，民尽屠戮，十存二三。”

“家家燕子巢空林，伏尸如山莽充斥……死者无头生被掳，有头还与无头伍。血泚焦土掩红颜，孤孩尚探娘怀乳。”

27.永昌之屠

顺治十六年、南明永历十三年(1659年)闰三月，清朝“征南将军”赵布泰、“提督”线国安等在云南永昌府等地进行的一次大规模屠城。

经过清军的大屠杀后，明朝年间有5000多万人，到来清朝康熙年间只剩1063万，少了2000万人。这其中虽然也有死于瘟疫和明朝内战的，但大部分还是还是被清军所杀。

以史为鉴，可知兴替，可警醒世人，不再重蹈覆辙，再遭如此国耻国难！

再看看我大清：

首先，清朝自己发布过大量屠杀文告，其中最著名的，是清朝官方资料《清世祖实录》

卷十七 顺治二年六月丙寅中的记录：

“自今布告之后，京城内外，直隶各省，限旬日尽行剃完。若规避惜发，巧词争辩，决不轻贷”。

并宣称：“所过州县地方，有能削发投顺，开城纳款，即与爵禄，世守富贵。如有抗拒不遵，大兵一到，玉石俱焚，尽行屠戮。”

清朝在四川1649年的另一份文告，口气也非常类似：“民贼相混，玉石难分。或屠全城，或屠男而留女”。

清朝另一份官方史料，《东华录》

卷五顺治元年条，则记载：“不随本朝制度剃发易衣冠者，杀无赦。”

镇江知府告示则是：“一人不剃发全家斩，一家不剃全村斩”，并将反抗者的人头，集中起来恐吓人民。

顺治二年（1645年），江宁巡抚土国宝宣布：“剃发、改装是新朝第一严令，通行天下，法在必行者，不论绅士军民人等，留头不留发，留发不留头！南山可移，此令不可动！ ”

在以上清朝官方的宣告中，充斥了大量“屠全城”、“尽行屠戮”、“杀无赦”、“全家斩”、“全村斩”的凶恶威胁。而下面列举的资料，则证明，清朝的公开威胁，绝不仅仅停留在口头。

辽东屠杀

天命九年正月，努尔哈赤下九次汗谕，清查所谓“无谷之人”，并谕令八旗官兵“应将无谷之人视为仇敌”，“捕之送来”，最后于正月二十七日下令:“杀了从各处查出送来之无谷之尼堪”。

天命十年十月初三日，努尔哈赤指责汉民“窝藏奸细，接受札付，叛逃不绝”，命令八旗贝勒和总兵官以下备御以上官将，带领士卒对村庄的汉人， “分路去，逢村堡，即下马斩杀”。

“时奴贼既得辽阳，辽东八站军民不乐从胡者，多至江边…… 其后，贼大至，义民不肯剃头者，皆投鸭水(鸭绿江)以死。”朝鲜 《朝鲜王朝实录》

掠夺虐杀汉族奴隶

崇祯十一年冬至十二年春，清军在畿辅
、山东一带掠去汉民四十六万二千三百馀人，崇祯十五年冬至十六年夏，清军又“俘获人民三十六万九千名口”。(《清太宗实录》

)满清入关后，继续劫掠人口。顺治二年八月辛巳日谕兵部“俘获人口，照例给赏登城被伤之人。”(《清世祖实录》)

汉人奴隶遭受非人的虐待，大量自杀。康熙初年，“八旗家丁每岁以自尽报部者不下二千人”(《清史稿》

)，仅自杀的汉人，在满清入关前后几十年间，就不下10万人。被虐待致死的，更不在少数。

由于满清的疯狂虐待，大量汉人奴隶逃亡，“只此数月之间，逃人已几数万。”(《清世祖实录》)

满清统治者为了制止逃往，强化其1626年颁布的《逃人法》

，顺治帝颁订:“有隐匿逃人者斩，其邻佑及十家长、百家长不行举首，地方官不能觉察者，俱为连坐”。顺治六年又改为“隐匿逃人者免死，流徙”、“再行申饬，自此谕颁发之日为始，凡章奏中再有干涉逃人者，定置重罪，决不轻恕”。(《清世祖实录》)

华北

畿南之屠

畿南之屠指的是公元1644年（明崇祯十七年五月），满清睿亲王多尔衮在北直隶三河、昌平、良乡等地进行的一次大规模屠城。根据《清世祖实录》记载，1644年五月，大顺军西撤。满清军队占领畿南地区，强令汉族剃发易服

。当地汉族居民纷纷揭竿而起，反对满清统治。满清朝廷派出军队弹压，对起义者和居民大肆屠戮，连老幼亦不能幸免。大约有五千人被屠杀。史称畿南之屠。

曹州之屠

曹州之屠指的是公元1649年（南明永历三年十月初四日），满清梅勒章京
赖恼、沂州总兵佟养量、临清总兵宜永贵等在山东州曹州进行的一次大规模屠城。根据《曹州志》和《重修大名府志》等记载，1649年原明东平侯刘泽清

密谋与亲信李化鲸反正归明。李化鲸部义军占领鲁西南州县，后为清军三省大军围剿，战败被俘，刘、李两人遇害。满清军入城后屠杀无遗。被屠杀的无辜居民人数不详。史称曹州之屠。

大同屠杀

大同之屠指的是公元1649年（南明永历三年八月二十九日），满清“皇父摄政王”多尔衮、“英亲王”阿济格
、“敬谨亲王”尼堪、“端重亲王”博洛

、“承泽亲王”硕塞等在山西大同府、朔州、浑源县等地进行的一次大规模屠城。

根据《清世祖实录》记载，1648年（永历二年），满清“大同总兵”姜瓖

反正归明，义军迅速占领晋西北、晋南广大地区，直接威胁满清朝廷。清廷调取华北地区绝大部分可以调派的军队进剿，历时将近一年才复占山西全境。姜瓖被叛徒汉奸杀害，大同城破，全城官吏兵民被屠杀。被屠杀的无辜居民人数不详。史称“大同之屠”。

清军实施大同大屠杀后，全城只剩下5个重案犯。满清派来的大同知府，上书顺治，称既然没有了苦主，就可以释放这5个人了。这份奏折，至今保存在第一历史档案馆。

参考文献：“清人所至，无不狼藉，尸则无完肤，人则无完发，烧杀抢掠，乃贼人之便饭矣。”

朔州之屠

朔州之屠指的是公元1649年（南明永历三年八月二十九日），满清“皇父摄政王”多尔衮、“英亲王”阿济格、“敬谨亲王”尼堪、“端重亲王”博洛、“承泽亲王”硕塞等在山西大同府、朔州、浑源县等地进行的一次大规模屠城。

关于朔州的这次屠城，根据《清世祖实录》记载，“顺治六年，大同、朔州、浑源三城，已经王师屠戮，人民不存”！《朔州志》

：“城破，悉遭屠戮”，“王师致讨，大兵临城，玉石俱焚，家破人亡……荡然一空”。

汾州之屠

汾州之屠指的是公元1649年（南明永历三年九月至十一月），满清“端重亲王”博洛、“和硕亲王”满达海等在山西汾州、太谷县、泌州、泽州等地进行的一次大规模屠城。

根据《清世祖实录》、《泽州志》
和《明清史料》记载，1649年大同失陷后，满清派出军队对晋南地区开展大扫荡，在各地实施大屠杀。明朝巡抚姜建勋

、监军道何守忠等殉国。大约有四十万人被屠杀。史称汾州之屠。
江淮

泾县之屠

泾县之屠是顺治二年（1645）原明代泾县县令尹民兴流寓泾县，与本县县城诸生赵初浣等率众拒清，据城坚守。清军提督张天禄

于八月十六日黎明，统铁骑百余，据东山发炮，城中屋瓦皆震，尹民兴走脱，赵初浣等战死。城陷，男女少长多罹难，仅遗民九十余人。县治官厅公署悉毁于兵火。史称泾县之屠或者乙酉之难。

泾县之屠指的是公元1646年（南明隆武二年八月十七日前后），满清“提督”张天禄、“池州总兵”于永绶

在南直隶泾县、徽州、绩溪县等地进行的一次大规模屠城。

根据《明清史料》等记载，1646年皖南人民不能容忍满清政权的剃发易服而发动起义，反抗满清统治。义军攻略皖南诸县后，因兵力不足，为满清军队所败。满清军在皖南地区展开疯狂的报复性大屠杀，其中以泾县特为尤甚。大约有五万人被屠杀。史称泾县之屠或乙酉之难。

江南

扬州十日

南明弘光元年，清朝顺治二年(1645年)发生在清军攻破扬州城后对城中平民进行大屠杀的事件。由于当时南明将领史可法
对清军的殊死抵抗，在同年四月廿五日(5月20日)，清军攻占扬州后，当时大雨倾盆，多铎宣布在扬州城内进行了屠杀。当时的幸存者王秀楚

所著《扬州十日记》中记载屠杀共持续十日，故名“扬州十日”。

清军攻破扬州城后进行了为期十天的大肆屠杀，史载:“诸妇女长索系颈，累累如贯珠，一步一跌，遍身泥土;满地皆婴儿，或衬马蹄，或藉人足，肝脑涂地，泣声盈野。”“初四日，天始霁。道路积尸既经积雨暴涨，而青皮如蒙鼓，血肉内溃。秽臭逼人，复经日炙，其气愈甚。前后左右，处处焚灼。室中氤氲，结成如雾，腥闻百里。”后来由城内僧人收殓的尸体就超过了80万具。

嘉兴大屠杀

南明弘光元年(1645年)闰六月二十六日，浙江布政使司
隶嘉兴府为反抗清军暴行，嘉兴民众揭竿而起，乡的明翰林学士屠象美、明兵科给事中李毓新主其事，降清的明嘉兴总兵陈梧

反正任大将军指挥义师，前吏部郎中钱棅助饷。二十六日城陷，逃不出的居民除大批年轻妇女被清军掳掠和一些僧人幸免外，几乎全遭屠杀。按当时人口来推，可能约500，000余人遇难。

江阴八十一日

江阴八十一日是指1645年夏江阴人民为抵制剃发令，在江阴典史：阎应元
、陈明遇、冯厚敦等人领导下进行的斗争。因为前后长达81天之久，故被称为“江阴八十一日”。（参考百家讲坛纪连海

先生的江阴八十一日讲座）

此役，10万江阴百姓面对24万清军铁骑，两百多门红衣大炮，血战孤城，抗清81日，击毙清军7万5千余人，亲王3名，大将军18名，最后城破，屠城，无一人降，城内死者九万七千余人，城外死者七万五千余人。阎应元、陈明遇、冯厚敦被后世称为“江阴抗清三公”。后世传纪对江阴的评价：“有明之季，士林无羞恶之心。居高官、享重名者，以蒙面乞降为得意；而封疆大帅，无不反戈内向。独阎、陈二典史乃于一城见义。向使守京口如是，则江南不至拱手献人矣。”此言甚当，沧江横流方显英雄本色，在各地望风披靡之时，阎应元以微末下吏凭借江阴百姓的支持，面对强敌，临危不惧，坚持了近三个月，击杀清寇数万人，重挫了清军锐气，钳制了清寇主力南下，推动了各地的抗清斗争。在城破以后，仍拚死巷战，“竟无一人降者”。

清初，扬州、嘉定、江阴等城，发源于老百姓的英勇抵抗，宁为玉碎不为瓦全，在华夏反侵略史上留下光彩夺目的一页。有章服之美称之华，有礼仪之大谓之夏。誓不与鞑子同流合污。

参考文献：“满城杀尽，然后封刀。……城中所存无几，躲在寺观塔上隐僻处及僧印白等，共计大小五十三人。是役也，守城八十一日，城内死者九万七千馀人，城外死者七万五千馀人。”《江阴城守纪》

嘉定三屠
嘉定三屠，指1645年（南明弘光元年，清朝顺治二年）清军攻破嘉定后，清军将领李成栋

三次下令对城中平民进行大屠杀的事件。

清军颁布剃发令，嘉定百姓拒不从命。乡绅侯峒曾
带领嘉定绅民起义反清，清吴淞

总兵李成栋立即领兵五千来攻。

嘉定城城破，李成栋下令屠城，市民之中，悬梁者，投井者，投河者，血面者，断肢者，被砍未死手足犹动者，骨肉狼籍。妇女们惨遭强奸。如遇抵抗，军队就用长钉把抵抗妇女的双手钉在门板上，然后再肆行奸淫。大屠杀持续了一天，直到尸体堵塞了河流，大约有三万多人遇害。李成栋率军离开嘉定城。

但嘉定城的劫难仍然没有结束。李成栋大屠杀后的三四天，侥幸逃脱的嘉定的幸存者开始溜回城里。他们回城后在一个叫做朱瑛

的义士领导下，重新集结起来，共两千多人。朱瑛领导着幸存者们在这座残破的城市展开了一场反屠杀运动，处死了归降清军的汉奸和清军委派的官吏。

李成栋又领着军士直杀入城里，把许多还在睡梦中的居民杀个精光，积尸成丘，然后放火焚尸。清军杀得兴起，嘉定又惨遭“二屠”。

二十多天后，原来南明的一个名叫吴之番

的将军率余部猛攻嘉定城，周边民众也纷纷响应，杀得城内清兵大溃出逃。不久，李成栋整军反扑，把吴之番数百士兵砍杀殆尽，顺带又屠杀了近二万刚刚到嘉定避乱的民众，血流成渠，是为著名的“嘉定三屠”。

参考文献：“市民之中，悬梁者，投井者，投河者，血面者，断肢者，被砍未死手足犹动者，骨肉狼籍。” 清兵“悉从屋上奔驰，通行无阻。城内难民因街上砖石阻塞，不得逃生，皆纷纷投河死，水为之不流。”“日昼街坊当众奸淫。”有不从者，“用长钉钉其两手于板，仍逼淫之。”，“兵丁每遇一人，辄呼蛮子献宝，其入悉取腰缠奉之，意满方释。遇他兵，勒取如前。所献不多，辄砍三刀。至物尽则杀。”(《嘉定乙酉纪事》

)

常熟大屠杀

“通衢小巷，桥畔河干，败屋眢井，皆积尸累累，通记不下五千馀人，而男女之被掳去者不计焉。”“沿塘树木，人头悬累累，皆全发乡民也。”(《海角遗编》)

昆山大屠杀

昆山之屠
的时间是是公元1645年（南明弘光元年七月初六日），昆山县人民杀该县清委知县阎茂才，起兵反清，引起满清“吴淞总兵”李成栋、“刑部侍郎”李延龄

在南直隶昆山县进行的一次大规模屠城。

根据《归庄年谱》、《顾炎武
年谱》和《研堂见闻杂记》记载，1645年满清军队进攻昆山县，昆山县绅民在原郧阳抚院王永祚

等人倡义下，起兵反清。顾炎武、归庄等爱国志士都积极参与义举。七月初六清军攻陷昆山后，大肆屠城。大约有四万人被屠杀。史称昆山之屠。

参考文献：“总计城中人被屠戮者十之四，沉河堕井投缳者十之二，被俘者十之二，以逸者十之一，藏匿幸免者十之一。”(《昆新两县续修合志》

卷五一兵纪)，“杀戮一空，其逃出城门践溺死者，妇女、婴孩无算。昆山顶上僧寮中，匿妇女千人，小儿一声，搜戮殆尽，血流奔泻，如涧水暴下”!((研堂见闻杂记))

金华之屠

金华之屠指的是公元1646年（南明隆武二年七月十六日），满清“贝勒”博洛在浙江金华府进行的一次大规模屠城。

根据《浙东记略》、《临安旬制记》、《金华府志》和《金华县志
》等记载，1646年五月，满清军队攻占浙东府县，南明钱塘江防线沦陷，鲁监国放弃绍兴，转进至海上。兴国公王之仁、大学士张国维

等义士杀身殉国。金华人民在督师大学士朱大典带领下据城而战，誓死不降。满清军队攻陷金华后，借口民不顺命，屠城。大约有五万人被屠杀。史称金华之屠。

赣州之屠

赣州之屠指的是公元1646年（南明隆武二年十月初四日），满清“江西提督”金声桓

、“总兵”柯永盛在江西赣州府进行的一次大规模屠城。

根据《赣州府志》

、《赣县志》、《行朝录》和《仿指南录》记载，1646年三月，满清军队从南昌南下，击破沿路明军。赣州府防守力量由各地援军组成，缺乏协同作战能力，不久后沦陷。满清军攻占赣州后，江西总督万元吉、武英殿大学士杨廷麟等与六千守城将士殉国，满清军屠城。大约有二十万人被屠杀。史称赣州之屠。

平海之屠
平海之屠指的是公元1647年（南明永历元年七月），清军在福建平海卫

进行的一次大规模屠城。

根据《明清史料》、《南明史》

等记载，1647年南明绍宗皇帝殉国后，遵奉鲁监国的义师在闽浙两地依然相当活跃。是年七月，南明同安伯杨耿领兵一度收复平海卫。满清援军赶到后，杨耿兵被迫撤退，平海卫百姓惨遭屠杀。被屠杀的无辜百姓具体人数不详。史称平海之屠。

邵武之屠
邵武之屠指的是公元1648年（南明永历二年四月），满清“福建左路总兵”王之纲

在福建邵武县进行的一次大规模屠城。

根据《郑成功档案史料选集》等记载，1648年江西金声桓、王得仁

反正归明后，福建义民举兵响应。义军攻占邵武县城后，复为满清兵所败，城中起而响应的绅民惨遭屠戮。被屠杀的无辜百姓人数不详。史称邵武之屠。

同安之屠

同安之屠指的是公元1648年（南明永历二年八月十六日），满清“靖南将军”陈泰、“浙闽总督”陈锦、“福建提督”赵国祚

在福建同安县进行的一次大规模屠城。

根据《郑成功档案史料选集》等记载，1648年李成栋反正后，闽南地区复归明朝旗下，但闽系将领多为排斥。是年七月满清军队进攻同安，郑成功援军因风向不利受阻。同安城破后，守城将士悉数杀身成仁，满清军队屠城，血流沟渠。大约有五万人被屠杀。史称同安之屠。

湘潭大屠杀

1649年正月二十一日清军攻入湘潭，南明督师何腾蛟
被俘。清郑亲王济尔哈朗下令屠城，“屠至二十六日封刀，二十九日方止”。湘潭城中百姓几乎全被杀光，城中不满百人。”(康熙三年《湘潭县志》

)

南昌大屠杀

1648年，金声桓、王得仁在江西起兵抗清，七月初十清军包围南昌。次年三月间，南昌城陷，清军屠城。

“妇女各旗分取之，同营者迭嬲无昼夜。三伏溽炎，或旬月不得一盥拭。除所杀及道死、水死、自经死，而在营者亦十余万，所食牛豕皆沸汤微 ?集而已。饱食湿卧，自愿在营而死者，亦十七八。而先至之兵已各私载卤获连轲而下，所掠男女一并斤卖。其初有不愿死者，望城破或胜，庶几生还;至是知见掠转卖，长与乡里辞也，莫不悲号动天，奋身决赴。浮尸蔽江，天为厉霾。”(徐世溥《江变纪略》

)

华南

信丰之屠

信丰之屠指的是公元1649年（南明永历三年三月初一日），满清“梅勒章京”胶商在广东信丰县进行的一次大规模屠城。

根据《西江志》等记载，1649年李成栋二次入赣，为满清军所败，退守信丰。满清军攻破城池，李成栋仓促撤退，在回师过程中阵亡。满清军入城后对城中居民滥加屠杀。被屠杀的无辜居民人数不详。史称信丰之屠。

南雄大屠杀

雄之屠指的是公元1649年（南明永历三年十二月三十日），满清“平南王”尚可喜

、“靖南王”耿继茂在广东南雄府进行的一次大规模屠城。

根据《岭表纪年》

、《南雄府志》记载，1649年清军从江西南下进攻广东，偷渡梅岭后，派遣间谍进入南雄放火并打开城门，满清军主力拥入。守城六千余名将士死战殉国，城内居民被屠戮殆尽。大约有两万人被屠杀。史称南雄之屠。

1649年农历十二月二十九日，清军抵达南雄，年三十除夕晚上清军放火焚烧鼓楼，趁明军慌乱救火之际，攻入城内。对南雄县民大肆屠杀，“大清平、靖二藩克雄城，民尽屠戮，十存二三。”(乾隆十八年《南雄县志》)

参考文献：“ 家家燕子巢空林，伏尸如山莽充斥。….死者无头生被掳，有头还与无头伍。血泚焦土掩红颜，孤孩尚探娘怀乳。(清军文书陈殿桂，《雄州店家歌》

)

庚寅之劫（又称广州大屠杀）

庚寅之劫，指1650年（清顺治七年，南明永历四年，庚寅年）11月24日到12月5日清朝军队在广州的屠城暴行。

当年公历11月24日，清朝平南王尚可喜与靖南王耿继茂指挥的清军（汉军镶蓝旗）在围城近十个月后，经过惨烈的战斗，包括筑垒相逼，以楼车攻城，及动用荷兰炮手，终于攻破广州城，随后对据城死守的广州居民进行了长达十二天的大屠杀，据清代官方史载，这场屠城，斩“兵民万余”，又“追剿余众至海滨，溺死者无算”，不论男女老幼，一律残酷地杀死，死亡人数根据收尸的和尚统计至七十万。

广州市社会科学研究所认为“七十万人”显然不可信，因为明末广州府

十三县人口总共才40万人。另有意见认为当时广州人口约40万，而死难者约十万人或超过十万人。

参考文献：“甲申更姓,七年讨殛。何辜生民，再遭六极。血溅天街，蝼蚁聚食。饥鸟啄肠，飞上城北。北风牛溲，堆积髑髅。或如宝塔，或如山邱。五行共尽，无智无愚，无贵无贱，同为一区。”(《祭共冢文》
王鸣雷)，“可喜屠广州，孑遗无留;逸出城者，挤之海中。”(倪在田《续明纪事本末》)《广州市宗教志》:“清顺治七年(1650年)，清军攻广州，‘死难10万至70万人。’在东郊乌龙冈

真修和尚雇人收拾尸骸，‘聚而殓之，埋其馀烬’合葬立碑”。

意大利籍耶酥会士卫匡国(Martin Martini

，1614~1661)在《鞑靼战纪》中记述:“大屠杀从11月24日一直进行到12月5日。他们不论男女老幼一 律残酷地杀死，他们不说别的，只说:‘杀!杀死这些反叛的蛮子!”荷兰使臣约翰纽霍夫(John Nieuhoff)在其《在联合省的东印度公司出师中国鞑靼大汗皇帝朝廷》一书记述:“鞑靼全军入城之后，全城顿时是一片凄惨景象，每个士兵开始破坏，抢走一切可以到手的东西;妇女、儿童和老人哭声震天;从11月26日到12月15日，各处街道所听到的，全是拷打、杀戮反叛蛮子的声音;全城到处是哀号、屠杀、劫掠;凡有足够财力者，都不惜代价以赎命，然后逃脱这些惨无人道的屠夫之手。”

潮州之屠

潮州之屠指的是公元1653年（南明永历七年九月十四日），满清“靖南将军”哈哈木在广东潮州府进行的一次大规模屠城。

根据《平南王元功垂范》等记载，1653年九月，是年满清“潮州总兵”郝尚久

反正归明，响应李定国大军。李定国兵败西撤后，郝尚久势单力薄。满清军队在包围潮州一月有余之后，攻陷府城，郝尚久自杀殉国。满清军屠城，斩杀无算。大约有十万人被杀，史称潮州之屠。

参考文献：“纵兵屠掠，遗骸十余万”，揭阳县观音堂海德和尚等收尸聚焚于西湖山，将骨灰葬在西湖南岩。福建同安县屠城死难5万余人，梵天寺主持释无疑收尸合葬于寺东北一里之地，建亭“无祠亭”，墓碑上则刻“万善同归所

”。

西南

四川大屠杀

清军入关后的1647年在四川公开发布告示，宣称：全城尽屠，或屠男而留女。把四川人杀光了以后，就把罪恶全部推给也杀了一点人的张献忠，还编造出张献忠杀人6个亿的历史第一大谎言！根据近年历史学者的研究，四川被害者不下300万，而被张献忠杀害的至多只有14万人，连同张献忠统制地区其它非正常死亡，最多只有30-40万人。更重要的是，在清军开始长达十几年的四川大屠杀前，张献忠已经死了。

南明隆武二年( 1646 年)至永历十九年( 1665年)十一月，张献忠阵亡，满清开始侵入四川。同年满清政府贴出公告:“民贼相混，玉石难分。或屠全城，或屠男而留女”。面对四川人民顽强不屈的抵抗，此后满清用了近20年时间始占领四川。1647年清将张德胜
攻入成都被杀后，相继攻伐四川的清军有高民瞻、吴三桂、李化龙等部。1660年，成都沦陷;1663年，重庆沦陷;1665年，南明下川东战役失利，全蜀沦陷。四川的反清活动被残忍地镇压后，满清“叔父摄政王”多尔衮、孝庄采取了彻底屠杀的办法作为报复，约5，400，000人遇难。最后到了“弥望千里，绝无人烟”的地步。后来清廷不得不迁移湖广的人口至四川(即有名的以湖广填四川

)。

永昌之屠

永昌之屠指的是公元1659年（南明永历十三年闰三月），满清“征南将军”赵布泰

、“提督”线国安等在云南永昌府等地进行的一次大规模屠城。

根据《清世祖实录》和《明清档案》

记载，1659年满清军队进入云南，分路攻打南明防线。满清军队沿途烧杀抢掠无恶不作，永昌一带周围百里无人烟。被屠杀的无辜居民人数不详。史称永昌之屠。

西北

潼关之屠

潼关之屠指的是公元1644年（明崇祯十七年正月十三日），满清“豫亲王”多铎在陕西潼关进行的一次大规模屠城。

根据《清世祖实录》和《潼关志》
记载，1644年正月十二日，李自成从潼关回援西安。留守潼关的大顺“巫山伯”马世耀

向满清军队诈降，但密信为满清所获。次日，多铎诈称举行宴会，将马部官兵解除武装，手无寸铁的战俘被尽数屠杀。

&lt;h2 id=&quot;满清大屠杀&quot;&gt;满清大屠杀&lt;/h2&gt;

&lt;h3 id=&quot;扬州十日&quot;&gt;扬州十日&lt;/h3&gt;

南明弘光元年，清朝顺治二年(1645年)发生在清军攻破扬州城后对城中平民进行大屠杀的事件。
由于当时南明将领史可法对清军的殊死抵抗，在同年四月廿五日(5月20日)，清军攻占扬州后，当时大雨倾盆，多铎宣布在扬州城内进行了屠杀。
当时的幸存者王秀楚所著《扬州十日记》中记载屠杀共持续十日，故名“扬州十日”。

清军攻破扬州城后进行了为期十天的大肆屠杀，史载:“诸妇女长索系颈，累累如贯珠，一步一跌，遍身泥土;满地皆婴儿，
或衬马蹄，或藉人足，肝脑涂地，泣声盈野。”“初四日，天始霁。道路积尸既经积雨暴涨，而青皮如蒙鼓，血肉内溃。
秽臭逼人，复经日炙，其气愈甚。前后左右，处处焚灼。室中氤氲，结成如雾，腥闻百里。”后来由城内僧人收殓的尸体就超过了80万具。

&lt;img src=&quot;../images/20250903-1.png&quot; alt=&quot;&quot; /&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.ziyexing.com/files-5/guwen/guwen-17.htm&quot;&gt;扬州十日记·译文 [明·王秀楚]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;其他&quot;&gt;其他&lt;/h2&gt;

一、剃发令：扬州十日、嘉定三屠，屠戮了3000万平民。

满清强制推行剃发易服，将汉人及所有其他族人统一剃发留辫，并以此为区分满汉和尊卑等级的标志。

二、文字狱：大兴文字狱150年，被凌迟杀害者无数。

满清入主中原后，为了巩固统治，防止汉人反抗，设立了文字狱，对著作、诗文、书信等文字作品进行审查，摘取文字意会而成罪名。这种禁锢思想的行为造成了对知识分子的严重打压，因为文字狱而被诛九族的达到上百起。导致社会文化的发展停滞。

明史案——由庄廷鑨编写《明史》而引发的清初最大的文字狱案。双目皆盲的浙江湖州富户庄廷鑨出钱购买明人朱国祯一部未完成的《明史》，然后延揽名士，增润删节，补写崇祯朝和南明史实，其父庄允诚于顺治十七年冬（公元1660年）将书刻成，即行刊书《明史辑略》。

顺治十八年（公元1661年）为归安知县吴之荣告发，这时廷鑨已死，被掘墓刨棺，枭首碎骨，尸体被悬吊在杭州城北关城墙上，示众三个月，廷鑨弟廷钺被杀。所有列名参校、刻印买卖者均因此获罪 ，重辟70余人，凌迟18人。

三、焚书：清朝乾隆年间大兴文字狱，毁灭经典书籍、科学书籍禁毁图书13600卷。

焚书总数达15万册，销毁版片170余种、80000余块。对明朝不少于10000件的档案进行销毁，目前仅存3000余件。

乾隆39年开始，武英殿前字纸炉日夜燃烧，严密监视下，巨量珍贵图书灰飞烟灭，随同消灭的是一个民族的大量记忆。

四、闭关锁国

清朝实行闭关锁国政策，限制了对外贸易和文化交流，使中国错失了学习先进科学知识和生产技术的机会，导致中国在科技和军事上远远落后于西方。

五、大肆出卖中国土地，割地赔款

在中外签订的多个不平等条约中，中国丧失了大片领土和主权。在面对俄罗斯小股民兵侵略时，居然和俄罗斯签订《尼布楚条约》主动放弃西伯利亚大片领土，甚至连自古属于中国的瀚海湖（贝加尔湖）也放弃！

再后来，据资料记载，自1842年鸦片战争爆发后，清政府被迫和西方列强国家大大小小签订了700多份不平等条约。据不完全统计，清政府累计欠下的赔款超过了13亿两白银。

其中涉及到割地面积较大的条约共有4个，分别是1858年的《瑷珲条约》将黑龙江以东、外兴安岭以南的60多万平方公里领土割让给俄罗斯； 1860年的《北京条约》将乌苏里江以东44万平方公里的领土割让给俄罗斯； 1895年的《马关条约》，割让辽东半岛、台湾岛及其附属岛屿以及澎湖列岛共近10万平方公里的领土给日本； 1861年俄罗斯逼迫清政府签下的《塔城界约》，侵占了我国自沙渍达巴哈起，至葱岭止约43万平方公里领土。

六、搞愚民政策，奴化政策，贫民政策。

多年的政策下，国民识字率1%都不到，而且极度贫穷、奴性。鸦片肆虐，导致中国人被称为“东亚病夫”。

七、禁止汉人对外移民

近代是大移民时代，欧洲人大量移民美洲澳洲，汉族本应参与大移民的浪潮，满清为了奴役压迫汉族，故意不让汉族往外移民，使汉族丢失了往外移民的机会和前途。

如果满清政府没有禁止汉族往外移民，现在全世界汉族国家可能已经多出好几个。

远的不说，就说巴西在清末向清政府请求移民中国人去巴西，却遭到清政府的严词拒绝。结果巴西去找日本，日本政府非常积极，移民几百万日本人去巴西。现在巴西有大量日本人，日本人在巴西拥有大量私人田地，甚至超过了日本本土，这些土地可以让日本在巴西繁衍大量人口。这一切本来都该是我们中国人的，然而却被满清故意破坏！

另外满清对汉人向东南亚的移民一直是排斥，压迫，封闭的政策。如果没有满清的故意阻挠，东南亚的汉族移民根本就不会那么少，应该早就建立了数个汉族国家。

比较有名的是兰芳共和国事件。

汉人自力更生在东南亚建立了兰芳共和国，由于实力弱小，面临欧洲侵略者的侵略，兰芳共和国寻求清朝的保护，没醒到满清政府居然大骂汉人向外移民是反叛，支持欧洲侵略者侵略兰芳共和国。最后兰芳共和国被欧洲侵略者消灭。

还有在马来半岛和苏门答腊岛，如果汉族可以自由移民完全可以在这个两个地区建国，但由于满清的一再阻挠和限制没有实现。现在当地土著越生越多汉族比例不断下降，再无独立的可能。马来西亚的汉族也由原来的40%下降为20%，印尼华人由原来的10%降为现在的3%。

八：盗墓

乾隆为了修陵墓，甚至去盗明十三陵，这种行为严重破坏了中国的历史文化遗产。

九、压制商人

明万历年间中国沿海一带已经出现了资本主义的萌芽，但满清的压制商人政策阻碍了中国经济的发展，使中国错失参与第二次工业革命的机会，导致中国落后挨打。

十、民族歧视

满清实行民族歧视政策，对汉人和其他族人进行不平等待遇，严重侵犯了汉族的权利和尊严。

&lt;h2 id=&quot;禁止私塾&quot;&gt;禁止私塾&lt;/h2&gt;

清朝通过封禁民间私塾、冷藉等措施，成功将民间识字率压制到不足1%，私自开私塾、私传所学严惩，家学所授课业严审。而且清廷焚烧、尽灭了大量科技类书籍，比如《天工开物》。

&lt;h2 id=&quot;满洲国流亡政府&quot;&gt;满洲国流亡政府&lt;/h2&gt;

这个词是我最近才看到的，一篇《满洲国流亡政府代表团访日》，2024年1月23日，满洲国流亡政府代表团在日本国会众议院会馆举办《印太战略与满洲复国运动》会议。

&lt;img src=&quot;../images/20250903-2.png&quot; alt=&quot;&quot; /&gt;

&lt;h2 id=&quot;参考资料&quot;&gt;参考资料&lt;/h2&gt;

2019年，公安部端掉了满遗复辟分裂组织“满洲复兴协和会”，抓获了18名妄图复辟清朝的骨干分子。也就是这件事情，让塔意识到所谓“清宫文化”和“辫子戏”的危害性有多大，从19年开始，广电也开始有意识的减少甚至封杀清宫剧的拍摄，曾经霸占市场二十余年的辫子戏到了人人喊打的地步，电视上可以看到很早之前拍摄的《雍正王朝》《康熙王朝》等古早电视剧，但19年之后几乎没有啥新出的电视剧了，最新的一个是2022年的《天下长河》

作者：上帝的左手
链接：https://www.zhihu.com/question/593861268/answer/1903376346786272890
来源：知乎
著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。
</description>
        <pubDate>Wed, 03 Sep 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/20250903/</link>
        <guid isPermaLink="true">https://wsdjeg.net/20250903/</guid>
        
        <category>满清</category>
        
        <category>历史</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>Lua 可变参数</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#参考文章&quot; id=&quot;markdown-toc-参考文章&quot;&gt;参考文章&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

在 Lua 中遇到需要使用可变参数时，通常这样处理：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 输出：&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

但是，如果传入的参数中间有 nil 那么，结果就不是预期的了：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 输出：&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

因此，在遍历参数时，推荐使用 select 函数：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;#&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 输出：&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;参考文章&quot;&gt;参考文章&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://ms2008.github.io/2016/10/09/lua-variable-args/&quot;&gt;Lua 正确处理可变参数&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 24 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-function-argvs/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-function-argvs/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>高效处理 Markdown 中的代码块</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#执行代码&quot; id=&quot;markdown-toc-执行代码&quot;&gt;执行代码&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#格式化代码&quot; id=&quot;markdown-toc-格式化代码&quot;&gt;格式化代码&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

在使用 Markdown 写作时，通常会在文章中需要插入代码块。为了更高效的编辑和执行代码块，引入以下几个插件及配置。

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Shougo/context_filetype.vim&quot;&gt;context_filetype.vim&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/wsdjeg/code-runner.nvim&quot;&gt;code-runner.nvim&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/wsdjeg/format.nvim&quot;&gt;format.nvim&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;执行代码&quot;&gt;执行代码&lt;/h2&gt;

新建 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.confg/nvim/ftplugin/markdown.lua&lt;/code&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;leader&amp;gt;lr&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;context_filetype#get&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filetype&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;markdown&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;runner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;code-runner&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filetype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;usestdin&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;range&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;range&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;range&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;code-runner&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;silent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;格式化代码&quot;&gt;格式化代码&lt;/h2&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;leader&amp;gt;bf&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;context_filetype#get&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filetype&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;markdown&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&apos;%s,%sFormat! %s&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filetype&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;silent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 24 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/code-block-in-markdown/</link>
        <guid isPermaLink="true">https://wsdjeg.net/code-block-in-markdown/</guid>
        
        <category>markdown</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>为什么停止维护 SpaceVim</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#项目的初衷&quot; id=&quot;markdown-toc-项目的初衷&quot;&gt;项目的初衷&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#遇到的问题&quot; id=&quot;markdown-toc-遇到的问题&quot;&gt;遇到的问题&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#停止维护的原因&quot; id=&quot;markdown-toc-停止维护的原因&quot;&gt;停止维护的原因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#归档即是新的开始&quot; id=&quot;markdown-toc-归档即是新的开始&quot;&gt;归档即是新的开始&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#插件列表&quot; id=&quot;markdown-toc-插件列表&quot;&gt;插件列表&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#插件管理器-nvim-plug&quot; id=&quot;markdown-toc-插件管理器-nvim-plug&quot;&gt;插件管理器 nvim-plug&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#项目管理-rooternvim&quot; id=&quot;markdown-toc-项目管理-rooternvim&quot;&gt;项目管理 rooter.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#异步代码检索-flygrepnvim&quot; id=&quot;markdown-toc-异步代码检索-flygrepnvim&quot;&gt;异步代码检索 flygrep.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#历史文件管理-mrunvim&quot; id=&quot;markdown-toc-历史文件管理-mrunvim&quot;&gt;历史文件管理 mru.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#代码格式化-formatnvim&quot; id=&quot;markdown-toc-代码格式化-formatnvim&quot;&gt;代码格式化 format.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#版本控制-gitnvim&quot; id=&quot;markdown-toc-版本控制-gitnvim&quot;&gt;版本控制 git.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#代码运行-code-runnernvim&quot; id=&quot;markdown-toc-代码运行-code-runnernvim&quot;&gt;代码运行 code-runner.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#书签管理-bookmarksnvim&quot; id=&quot;markdown-toc-书签管理-bookmarksnvim&quot;&gt;书签管理 bookmarks.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#tags-管理-ctagsnvim&quot; id=&quot;markdown-toc-tags-管理-ctagsnvim&quot;&gt;tags 管理 ctags.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#滚动侧栏-scrollbarnvim&quot; id=&quot;markdown-toc-滚动侧栏-scrollbarnvim&quot;&gt;滚动侧栏 scrollbar.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#笔记插件-zettelkastennvim&quot; id=&quot;markdown-toc-笔记插件-zettelkastennvim&quot;&gt;笔记插件 zettelkasten.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#日历插件-calendarnvim&quot; id=&quot;markdown-toc-日历插件-calendarnvim&quot;&gt;日历插件 calendar.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#异步job管理-jobnvim&quot; id=&quot;markdown-toc-异步job管理-jobnvim&quot;&gt;异步job管理 job.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#模糊搜索插件-pickernvim&quot; id=&quot;markdown-toc-模糊搜索插件-pickernvim&quot;&gt;模糊搜索插件 picker.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#项目文件跳转-altfnvim&quot; id=&quot;markdown-toc-项目文件跳转-altfnvim&quot;&gt;项目文件跳转 altf.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#按键弹窗-record-keynvim&quot; id=&quot;markdown-toc-按键弹窗-record-keynvim&quot;&gt;按键弹窗 record-key.nvim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#录屏-record-screennvim&quot; id=&quot;markdown-toc-录屏-record-screennvim&quot;&gt;录屏 record-screen.nvim&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

SpaceVim 从 2016 年 12 月诞生，到 2025 年 2 月 21 日正式归档，前后将近九年。
九年的时间足以让一个想法从萌芽走向成熟，也足以让一个项目逐渐找到它最合适的落点。
在我看来，归档并不意味着结束，也是新的一段开始。

&lt;h2 id=&quot;项目的初衷&quot;&gt;项目的初衷&lt;/h2&gt;

早期，开发这个项目的时候，是想做一个开箱即用的模块化 Vim 配置，类似于 spacemacs 那样，
把不同语言功能所需要的配置及插件都放到一个模块里面。使用者不再需要自己配置各种插件，
只需要简单地启用对应语言或者功能的模块就可以快速搭建 Vim 的开发环境。

&lt;h2 id=&quot;遇到的问题&quot;&gt;遇到的问题&lt;/h2&gt;

随着功能越来越多，代码越来越臃肿，速度也变得越来越慢。如果查看 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git log&lt;/code&gt; 的话，不难发现，
很大一部分内容是做速度的优化。

甚至，我也使用 Lua 重写的相当一部分的内置插件，包括状态栏、标签栏、任务管理、项目管理、多光标、快捷键导航等等。

但是即便是使用 Lua 进行了重写，但是因为要兼容老版本的 Neovim 以及兼容 Vim，因此整体总的框架使用的是 Vim Script，
调用 Lua 插件的时候还是使用 VimL 去调用 Lua 的代码，例如：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;func&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; SpaceVim#test&lt;span class=&quot;p&quot;&gt;(...)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;lua&lt;/span&gt; require&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;task&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;start&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;require&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;spacevim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;a:000&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这样的话速度还是无法发挥到极致。

&lt;h2 id=&quot;停止维护的原因&quot;&gt;停止维护的原因&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;想使用纯 Lua 来写 Neovim 配置（&lt;a href=&quot;https://github.com/wsdjeg/nvim-config&quot;&gt;nvim-config&lt;/a&gt;），不再兼容 Vim，因为我也很少再使用 Vim 了。&lt;/li&gt;
  &lt;li&gt;不想做 Neovim 老版本的兼容支持&lt;/li&gt;
  &lt;li&gt;单个功能插件独立维护，便于直接使用，我把原先 spacevim 中内置的很多功能，&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;归档即是新的开始&quot;&gt;归档即是新的开始&lt;/h2&gt;

归档并不是结束，而是完成一个阶段性作品后的放手。正如上述原因里所描述，我希望使用 Lua 并且不再兼容老版本以及 Vim，使得代码能够更简洁。
相较于再制作一个 Lua 开发的 SpaceVim，我更乐意把 SpaceVim 中日常使用较多的功能独立成单独的插件。这样也方便他人根据实际的需求选择最小化的配置。

&lt;h2 id=&quot;插件列表&quot;&gt;插件列表&lt;/h2&gt;

目前已经切换到纯 Lua 配置的 Neovim 环境了，并且原先 SpaceVim 中常用功能已单独使用 Lua 重写。

个人 Neovim 配置仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/nvim-config&quot;&gt;nvim-config&lt;/a&gt;。

以下是我自己制作并且日常使用的 Neovim 插件，欢迎尝试。

&lt;h3 id=&quot;插件管理器-nvim-plug&quot;&gt;插件管理器 nvim-plug&lt;/h3&gt;

&lt;img src=&quot;../images/nvim-plug.gif&quot; alt=&quot;nvim-plug&quot; /&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/nvim-plug&quot;&gt;wsdjeg/nvim-plug&lt;/a&gt;

这是我参考 &lt;a href=&quot;https://github.com/Shougo/dein.vim&quot;&gt;dein.nvim&lt;/a&gt; 以及 &lt;a href=&quot;https://github.com/VundleVim/Vundle.vim&quot;&gt;Vundle.vim&lt;/a&gt;
写的一个异步的插件管理器，已经实现了日常我对于插件管理器的要求：

&lt;ol&gt;
  &lt;li&gt;clone、pull、build 等操作都是多线程异步执行；&lt;/li&gt;
  &lt;li&gt;支持通过 autocmd、command、function 等方式触发延迟加载；&lt;/li&gt;
  &lt;li&gt;支持依赖管理、import 目录载入插件；&lt;/li&gt;
  &lt;li&gt;支持 luarocks;&lt;/li&gt;
&lt;/ol&gt;

对于插件管理器的界面，其实我需要的只是像 &lt;a href=&quot;https://github.com/VundleVim/Vundle.vim&quot;&gt;Vundle.vim&lt;/a&gt;，
以前使用 dein.nvim 时候，dein.nvim 是默认没有 UI 界面的，当时我写了一个 &lt;a href=&quot;https://github.com/wsdjeg/dein-ui.vim&quot;&gt;dein-ui.vim&lt;/a&gt;
用来展示插件安装的进度。

&lt;h3 id=&quot;项目管理-rooternvim&quot;&gt;项目管理 rooter.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/rooter.nvim&quot;&gt;rooter.nvim&lt;/a&gt;

在使用 Vim 编辑代码文件时，比较常用的一个功能是根据当前文件的路径自动将当前目录切换到项目的根目录。
这个功能以前我使用的是 vim-rooter 这个插件。

而 rooter.nvim 正是使用 Lua 重新实现该功能的 Neovim 插件，
不同的是，该插件额外提供了一些模糊搜索插件拓展，可以模糊搜索历史打开过的项目。

此外，这个插件还支持设置 callback 函数，当切换项目时自动执行。

&lt;h3 id=&quot;异步代码检索-flygrepnvim&quot;&gt;异步代码检索 flygrep.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/flygrep.nvim&quot;&gt;flygrep.nvim&lt;/a&gt;

日常阅读代码过程中还是经常需要搜索代码的，flygrep。插件会异步调用rg，并实时展示搜索结果。

&lt;h3 id=&quot;历史文件管理-mrunvim&quot;&gt;历史文件管理 mru.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/mru.nvim&quot;&gt;mru.nvim&lt;/a&gt;

类似于 v:oldfiles，解决的问题是Windows系统下路径格式问题，同时支持各种筛选选项。此外也提供了一个 telescope 拓展。

&lt;h3 id=&quot;代码格式化-formatnvim&quot;&gt;代码格式化 format.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/format.nvim&quot;&gt;format.nvim&lt;/a&gt;

很早以前，我使用的代码格式化插件是 neoformat，这是使用 VimScript 开发的插件，为了更快的速度体验，我使用 Lua 重新写了一个格式化插件，插件的基本逻辑参考了 neoformat。也支持 markdown 内代码块的格式化。

&lt;h3 id=&quot;版本控制-gitnvim&quot;&gt;版本控制 git.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/git.nvim&quot;&gt;git.nvim&lt;/a&gt;

可以这么说，这应该是我日常使用最多的插件，比如 :Git add，:Git commit，等等。

&lt;h3 id=&quot;代码运行-code-runnernvim&quot;&gt;代码运行 code-runner.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/code-runner.nvim&quot;&gt;code-runner.nvim&lt;/a&gt;

vscode 里面有一个非常著名的插件，叫做CodeRunner，就是快速运行当前文件，并在下面分屏显示运行结果。code-runner.nvim 实现了想类似的功能，不仅仅可以运行当前文件，还可以快速运行 markdown 文件内当前代码块。

&lt;h3 id=&quot;书签管理-bookmarksnvim&quot;&gt;书签管理 bookmarks.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/bookmarks.nvim&quot;&gt;bookmarks.nvim&lt;/a&gt;

可以标记当前行进入书签列表，支持添加备注内容，支持使用quickfix列表展示书签，也提供了一个 telescope 拓展以便于模糊搜索书签。

&lt;h3 id=&quot;tags-管理-ctagsnvim&quot;&gt;tags 管理 ctags.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/ctags.nvim&quot;&gt;ctags.nvim&lt;/a&gt;

自动为当前项目生成ctags数据库，同时更新 &amp;amp;tags 选项，以便于使用ctrl-]跳转到光标tags定义位置。

&lt;h3 id=&quot;滚动侧栏-scrollbarnvim&quot;&gt;滚动侧栏 scrollbar.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/scrollbar.nvim&quot;&gt;scrollbar.nvim&lt;/a&gt;

自动在当前窗口右侧绘制一个滚动条，提示当前文档滚动页大致的位置。

&lt;h3 id=&quot;笔记插件-zettelkastennvim&quot;&gt;笔记插件 zettelkasten.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/zettelkasten.nvim&quot;&gt;zettelkasten.nvim&lt;/a&gt;

这是一个做笔记的插件，支持标签内链，相互索引。

&lt;h3 id=&quot;日历插件-calendarnvim&quot;&gt;日历插件 calendar.nvim&lt;/h3&gt;

&lt;img src=&quot;../images/calendar-demo.gif&quot; alt=&quot;calendar.nvim&quot; /&gt;

仓库地址: &lt;a href=&quot;https://github.com/wsdjeg/calendar.nvim&quot;&gt;calendar.nvim&lt;/a&gt;

记笔或者待办事项的时候，很多时候需要一个日历视图，来快速看下哪一天有记录。而 calendar.nvim
就是这样一个支持拓展的简易日历视图，可以方便的查阅日历，配合拓展还可以在特定日期执行某个拓展操作。

我目前最常用的是配合 zettelkasten.nvim 插件来记录和查阅每日笔记。

&lt;h3 id=&quot;异步job管理-jobnvim&quot;&gt;异步job管理 job.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/job.nvim&quot;&gt;job.nvim&lt;/a&gt;

这是模拟 jobstart 的工具，基于libuv，可以用于异步执行命令。我的很多插件都是依赖这个job.nvim，比如插件管理器等等，需要异步执行外部命令的。

&lt;h3 id=&quot;模糊搜索插件-pickernvim&quot;&gt;模糊搜索插件 picker.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/picker.nvim&quot;&gt;picker.nvim&lt;/a&gt;

早期在使用 Vim 时，使用过 ctrl-p、unite.vim、denite.nvim 等等插件。从 Neovim 浮窗功能出来后，逐步切换到了 telescope.nvim。
但是近期发现这个插件似乎不怎么在维护了，再加上自己也有想法写一个模糊搜索插件，于是就有了 picker.nvim。

&lt;h3 id=&quot;项目文件跳转-altfnvim&quot;&gt;项目文件跳转 altf.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/altf.nvim&quot;&gt;altf.nvim&lt;/a&gt;

这个插件提供了一个命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:A&lt;/code&gt;，可以使用这个命令在头文件和C文件、或者源文件和测试文件等之间快速跳转。

&lt;h3 id=&quot;按键弹窗-record-keynvim&quot;&gt;按键弹窗 record-key.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/record-key.nvim&quot;&gt;record-key.nvim&lt;/a&gt;

有时候制作录屏的时候，需要展示自己按键的顺序，这个插件以弹窗的形式，在右下方展示按键的顺序。

&lt;h3 id=&quot;录屏-record-screennvim&quot;&gt;录屏 record-screen.nvim&lt;/h3&gt;

仓库地址：&lt;a href=&quot;https://github.com/wsdjeg/record-screen.nvim&quot;&gt;record-screen.nvim&lt;/a&gt;

屏幕录制的软件其实挺多的，这个插件通过后台调用 ffmpeg，支持录制声音、话筒、摄像头等等。
</description>
        <pubDate>Sat, 03 May 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/why-spacevim-is-archived/</link>
        <guid isPermaLink="true">https://wsdjeg.net/why-spacevim-is-archived/</guid>
        
        <category>neovim</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>解决 Windows 系统下输入法问题</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#遇到的问题&quot; id=&quot;markdown-toc-遇到的问题&quot;&gt;遇到的问题&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#实际原因&quot; id=&quot;markdown-toc-实际原因&quot;&gt;实际原因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#解决方法&quot; id=&quot;markdown-toc-解决方法&quot;&gt;解决方法&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#使用-neovim-autocmd-自动执行-im-select&quot; id=&quot;markdown-toc-使用-neovim-autocmd-自动执行-im-select&quot;&gt;使用 Neovim autocmd 自动执行 im-select&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#更好的解决方法&quot; id=&quot;markdown-toc-更好的解决方法&quot;&gt;更好的解决方法&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;遇到的问题&quot;&gt;遇到的问题&lt;/h2&gt;

最近更新 Windows 系统后，使用 ALT-Tab 快捷键切换窗口，每次切换回终端，输入法就会自动变成中文模式，非常影响 Neovim 的操作。

比如：每次切换到浏览器，复制下相关内容后，到 nvim 里面来想黏贴，通常使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;+p&lt;/code&gt; 快捷键就可以了，但是由于当前输入法变成了中文模式，
就变成输入了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;“+&lt;/code&gt;, Normal 模式下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;“&lt;/code&gt; 无用，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; 直接给换到下一行。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p&lt;/code&gt; 按键不会直接输入到终端，反而会弹出输入法候选框。

此外，由于自动切换到了中文输入，当想执行 Neovim 命令时，比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:w&amp;lt;Cr&amp;gt;&lt;/code&gt; 的时候，同样的按键顺序，就会变成了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;：w&lt;/code&gt;, 未保存，同时相当于 Normal 模式下执行了一次 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w&lt;/code&gt; 光标向前移动一个词位置。

&lt;h2 id=&quot;实际原因&quot;&gt;实际原因&lt;/h2&gt;

网上类似的讨论有很多：

&lt;ul&gt;
  &lt;li&gt;
    https://www.v2ex.com/t/1120452
  &lt;/li&gt;
  &lt;li&gt;
    https://chunyujin.top/chunyujin/8728f196
  &lt;/li&gt;
&lt;/ul&gt;

但是并没有讲到真实的原因。在以前的系统里面（Win7），通常语言设置会有两个键盘，一个叫做美式键盘（一个灰色小的键盘图标），
另外一个键盘通常就是我们的输入法，比如搜狗的红色小图标，日常最常用的快捷键是 ctrl-space 来切换的是键盘，而不是某个输入法的中英文模式。
有时候，还不止两个键盘，比如同时安装了搜狗拼音、搜狗五笔，那么加上默认的美式键盘，就是三个键盘。通常使用 ctrl-space 来回切换，ctrl-shift 轮换。
虽然，以前搜狗输入也好，微软输入法也好，大多数提供了内置的中英文输入切换，通常快捷键是 shift 键。
而在最新版的 Windows 系统中，微软做了一件非常恶心的的事情，就是默认不给你安装美式键盘，只给你安装一个微软输入法，
并且把默认的键盘切换按键ctrl-space改为win-space，同时无法改回，只能在微软输入法里面设置ctrl-space切换自己的中英文模式。

&lt;h2 id=&quot;解决方法&quot;&gt;解决方法&lt;/h2&gt;

设置 - 时间和语言 - 语言和区域 - 首选语言 - 添加语言 - 找到 English（United States）添加。

&lt;img src=&quot;../images/set-lang.png&quot; alt=&quot;&quot; width=&quot;400px&quot; /&gt;

此时就有两个键盘，使用 win-space 可以切换键盘。

&lt;img src=&quot;../images/im-select-1.png&quot; alt=&quot;&quot; width=&quot;400px&quot; /&gt;

美式键盘只做英文输入，微软拼音只做中文输入，关闭管软拼音的英文模式。

完成以上操作后就可以使用命令行工具 &lt;a href=&quot;https://github.com/daipeihust/im-select&quot;&gt;im-select&lt;/a&gt; 进行键盘切换了。

打开命令行窗口：分别在两个键盘模式下执行一次下载的 im-select.exe 可以看到输出如下：

&lt;img src=&quot;../images/im-select-cmd.png&quot; alt=&quot;&quot; width=&quot;400px&quot; /&gt;

关于这个命令的说明：

&lt;ol&gt;
  &lt;li&gt;直接不带参数执行，获取当前键盘值，比如上图中，我分别先后在美式键盘和微软拼音下单独执行命令，获取到两个键盘值 1033 和 2052。&lt;/li&gt;
  &lt;li&gt;执行命令，并带上键盘值参数，切换至指定键盘，比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;im-select.exe 1033&lt;/code&gt; 切换至美式键盘，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;im-select.exe 2052&lt;/code&gt; 切换至微软拼音。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;使用-neovim-autocmd-自动执行-im-select&quot;&gt;使用 Neovim autocmd 自动执行 im-select&lt;/h2&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;augroup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_autocmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 这里指定下载的 im-select.exe 的绝对路径，&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 当然，你也可以将这个命令丢 PATH 里，个人不喜欢污染 PATH&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imselect&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;C:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Users&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;wsdjeg&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Downloads&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;im-select.exe&apos;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;InsertLeave&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;FocusGained&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;CmdlineLeave&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;VimEnter&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;-- 切换至美式键盘&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imselect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;1033&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;FocusLost&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;-- 切换至微软拼音&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imselect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;2052&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;更好的解决方法&quot;&gt;更好的解决方法&lt;/h2&gt;

如果不想增加美式键盘，那么可以使用 &lt;a href=&quot;https://github.com/daipeihust/im-select/tree/master/win-mspy&quot;&gt;im-select-mspy&lt;/a&gt;，对应的 Neovim 配置如下：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;augroup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- download im-select-mspy from https://github.com/daipeihust/im-select/raw/refs/heads/master/win-mspy/out/x64/im-select-mspy.exe&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imselect&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;C:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Users&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;wsdjeg&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Downloads&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;im-select-mspy.exe&apos;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;imselect_cn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imselect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-k=ctrl+space&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;中文模式&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;imselect_en&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imselect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-k=ctrl+space&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;英语模式&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 使用 table 存储不同 buffer 的 Insert 模式下的输入法&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer_im&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;InsertLeave&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imselect&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;-- 这里说明下，再 Windows Terminal 内执行该命令输出的内容默认编码是 `cp936`,&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;-- 需要转码成 utf-8，同时，输出内容尾部有换行符，使用 trim 函数去除。&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;buffer_im&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iconv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;cp936&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;utf-8&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;imselect_en&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;InsertEnter&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;英语模式&apos;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer_im&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer_im&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;英语模式&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;-- 此处设置快捷键，可以在输入法按键设置里面查看，我选择的是使用 ctrl-space 切换中英文&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;-- 默认我记得是 shift，同时这个命令默认也是 `-k=shift`&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imselect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-k=ctrl+space&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer_im&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;FocusGained&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;CmdlineLeave&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;VimEnter&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;imselect_en&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;FocusLost&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;imselect_cn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Wed, 23 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-im-select-in-windows/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-im-select-in-windows/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 历史使用文件插件 mru.nvim</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#mrunvim-的特点&quot; id=&quot;markdown-toc-mrunvim-的特点&quot;&gt;mru.nvim 的特点&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#安装与配置&quot; id=&quot;markdown-toc-安装与配置&quot;&gt;安装与配置&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#leaderf-拓展&quot; id=&quot;markdown-toc-leaderf-拓展&quot;&gt;LeaderF 拓展&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

最近分享了一个自己制作 Neovim 的插件 &lt;a href=&quot;https://github.com/wsdjeg/mru.nvim&quot;&gt;mru.nvim&lt;/a&gt;，
用于管理历史访问过的文件列表。有人说，这样简单的功能 Neovim 本身就有。

没错，Neovim 和 Vim 一样，支持使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v:oldfiles&lt;/code&gt; 获取最近浏览的文件名称列表。
但是 Neovim 这一变量在 Windows 系统下面存在文件名称格式不一致的问题（&lt;a href=&quot;https://github.com/neovim/neovim/issues/25033&quot;&gt;neovim#25033&lt;/a&gt;）。
比如，一些使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v:oldfiles&lt;/code&gt; 的插件，如 telescope.nvim、dashboard.nvim 等，其列表内会出现一些重复的文件。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;D:/hello.txt
D:\hello.txt
d:/hello.txt
d:\hello.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此外，阅读&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h v:oldfiles&lt;/code&gt; 可以看到该变量虽然支持修改，但是并不会影响 shada 文件中存储的内容。
因此，在 Neovim 重启后，之前对 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v:oldfiles&lt;/code&gt; 这一变量的修改就会无效了。

&lt;h2 id=&quot;mrunvim-的特点&quot;&gt;mru.nvim 的特点&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    Windows 系统下统一的文件名格式，上述四种文件名称统一显示为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;D:/hello.txt&lt;/code&gt;，可以避免重复显示。
  &lt;/li&gt;
  &lt;li&gt;
    可以预设置多个正则表达式，当文件名称匹配上时，阻止其被加入文件浏览历史记录。

    &lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;mru&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ignore_path_regexs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/.git/&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/nvim/runtime/doc/&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    比如，在使用一些启动屏插件（dashboard.nvim）时，会在启动时显示近期打开过的文件，
如果前面打开过一些非文本类文件，比如图片类的，这类文件可以从浏览历史中去除掉。

    &lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;mru&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ignore_path_regexs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/.git/&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;.mp3$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;.png$&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    提供了 telescope.nvim 拓展，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Telescope mru&lt;/code&gt; 打开。
  &lt;/li&gt;
  &lt;li&gt;
    提供了修改 mru 文件列表的函数，Neovim 重启后任然有效。
  &lt;/li&gt;
  &lt;li&gt;
    增加了 picker.nvim 推展，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Picker mru&lt;/code&gt; 打开。
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;安装与配置&quot;&gt;安装与配置&lt;/h2&gt;

使用 &lt;a href=&quot;https://github.com/wsdjeg/nvim-plug&quot;&gt;nvim-plug&lt;/a&gt; 插件管理器进行安装：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/mru.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;mru&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;enable_cache&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;mru_cache_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;data&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/nvim-mru.json&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;ignore_path_regexs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/.git/&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;enable_logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- require wsdjeg/logger.nvim&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;-- sort file by last modified time or last enter time&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;-- `lastmod`, `lastread` or `lastenter`, default is `lastenter`&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;sort_by&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;lastenter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;leaderf-拓展&quot;&gt;LeaderF 拓展&lt;/h2&gt;

当然，如果并未使用 telescope，也可以自行拓展，使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require(&apos;mru&apos;).get()&lt;/code&gt; 获取历史记录文件名称列表。以 leaderf 为例：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:nmru&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...)&lt;/span&gt; abort
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lua&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;require&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;mru&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:nmru_acp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; abort
  exe &lt;span class=&quot;s1&quot;&gt;&apos;e&apos;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:line&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; function() wrapper&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;703&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;703&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;nb&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;patch1170&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:_SID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; abort
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;matchstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;sfile&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;SNR&amp;gt;\zs\d\+\ze__SID$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:_s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;SNR&amp;gt;&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:_SID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;_&apos;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;fstr&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...)&lt;/span&gt; abort
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;substitute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:fstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s:&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;g&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:fstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:_SID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; abort
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;matchstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;sfile&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;SNR&amp;gt;\zs\d\+\ze__SID$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:_s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;SNR&amp;gt;&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:_SID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;_&apos;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;fstr&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; abort
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;substitute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:fstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s:&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;g&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:Lf_Extensions&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;nmru&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt;       &lt;span class=&quot;s1&quot;&gt;&apos;source&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s:_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;s:nmru&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;-3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt;       &lt;span class=&quot;s1&quot;&gt;&apos;accept&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s:_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;s:nmru_acp&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;-3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt;       &lt;span class=&quot;s1&quot;&gt;&apos;supports_name_only&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt;       &lt;span class=&quot;s1&quot;&gt;&apos;supports_multi&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上为 VimL 写的 LeaderF 拓展，尝试了使用 Lua 来写，可读性更简单，但是似乎不起作用：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mru&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;mru&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mru_acp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;e &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Lf_Extensions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;nvimmru&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mru&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;accept&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mru_acp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;supports_name_only&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;supports_multi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 13 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-most-recently-used-files/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-most-recently-used-files/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 录制按键及屏幕</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#按键提示&quot; id=&quot;markdown-toc-按键提示&quot;&gt;按键提示&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#录屏插件&quot; id=&quot;markdown-toc-录屏插件&quot;&gt;录屏插件&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#硬件设备检查&quot; id=&quot;markdown-toc-硬件设备检查&quot;&gt;硬件设备检查&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#仅录制屏幕&quot; id=&quot;markdown-toc-仅录制屏幕&quot;&gt;仅录制屏幕&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#录制屏幕麦克风扬声器&quot; id=&quot;markdown-toc-录制屏幕麦克风扬声器&quot;&gt;录制屏幕、麦克风、扬声器&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#安装配置&quot; id=&quot;markdown-toc-安装配置&quot;&gt;安装配置&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#参考阅读&quot; id=&quot;markdown-toc-参考阅读&quot;&gt;参考阅读&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

以前偶尔也会录制一些动图，使用的是 LICEcap，这也是一个开源项目，但是不能录制成视频。
在网上搜到不少的录视频的软件，比较火热的是班迪录屏，但是我还是倾向于免费开源方案。

&lt;h2 id=&quot;按键提示&quot;&gt;按键提示&lt;/h2&gt;

Neovim 增加了一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.on_key&lt;/code&gt;，这个函数在按键按下后会触发。借助这个函数及 Neovim 的悬浮窗口，
实现了一个按键弹窗提示的效果插件 &lt;a href=&quot;https://github.com/wsdjeg/record-key.nvim&quot;&gt;record-key.nvim&lt;/a&gt;。
默认的着色是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Normal&lt;/code&gt; 高亮组，如果需要突出显示，可以设置为：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;record-key&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;max_count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;winhighlight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;NormalFloat:Todo,FloatBorder:WinSeparator&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;录屏插件&quot;&gt;录屏插件&lt;/h2&gt;

&lt;a href=&quot;https://github.com/wsdjeg/record-screen.nvim&quot;&gt;record-screen.nvim&lt;/a&gt; 是一个 Neovim 屏幕录制的插件，
借助 ffmpeg 这个命令和 Neovim 的异步机制。

&lt;h2 id=&quot;硬件设备检查&quot;&gt;硬件设备检查&lt;/h2&gt;

前面的设置是只录制桌面图像，但是在日常视频录制的过程中，还是会涉及到其他的一些设备，比如麦克风、摄像头、音响等等。

首先使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ffmpeg -list_devices true -f dshow -i dummy&lt;/code&gt; 命令获取设备列表：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ffmpeg version 7.1.1-full_build-www.gyan.dev Copyright (c) 2000-2025 the FFmpeg developers
  built with gcc 14.2.0 (Rev1, Built by MSYS2 project)
  configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-lcms2 --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-libdvdnav --enable-libdvdread --enable-sdl2 --enable-libaribb24 --enable-libaribcaption --enable-libdav1d --enable-libdavs2 --enable-libopenjpeg --enable-libquirc --enable-libuavs3d --enable-libxevd --enable-libzvbi --enable-libqrencode --enable-librav1e --enable-libsvtav1 --enable-libvvenc --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxeve --enable-libxvid --enable-libaom --enable-libjxl --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-dxva2 --enable-d3d11va --enable-d3d12va --enable-ffnvcodec --enable-libvpl --enable-nvdec --enable-nvenc --enable-vaapi --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libcodec2 --enable-libilbc --enable-libgsm --enable-liblc3 --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
  libavutil      59. 39.100 / 59. 39.100
  libavcodec     61. 19.101 / 61. 19.101
  libavformat    61.  7.100 / 61.  7.100
  libavdevice    61.  3.100 / 61.  3.100
  libavfilter    10.  4.100 / 10.  4.100
  libswscale      8.  3.100 /  8.  3.100
  libswresample   5.  3.100 /  5.  3.100
  libpostproc    58.  3.100 / 58.  3.100
[dshow @ 000001f024fc6d40] &quot;Integrated Camera&quot; (video)
[dshow @ 000001f024fc6d40]   Alternative name &quot;@device_pnp_\\?\usb#vid_13d3&amp;amp;pid_5419&amp;amp;mi_00#7&amp;amp;17d116b8&amp;amp;1&amp;amp;0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global&quot;
[dshow @ 000001f024fc6d40] &quot;麦克风阵列 (Realtek(R) Audio)&quot; (audio)
[dshow @ 000001f024fc6d40]   Alternative name &quot;@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{253B9838-6E9C-47DB-A420-848E63B3931C}&quot;
[in#0 @ 000001f024fad380] Error opening input: Immediate exit requested
Error opening input file dummy.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

从上述的输出内容，不难看出，目前支持的设备仅仅有摄像头&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Integrated Camera&lt;/code&gt;和麦克风&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;麦克风阵列 (Realtek(R) Audio)&lt;/code&gt;，并没有扬声器，解决方法如下：

一、鼠标右键点击桌面右下角音量图标

&lt;img src=&quot;../images/声音设置1.png&quot; alt=&quot;&quot; width=&quot;400px&quot; /&gt;

二、打开更多音量设置

&lt;img src=&quot;../images/声音设置2.png&quot; alt=&quot;&quot; width=&quot;400px&quot; /&gt;

三、点击录制、右击立体声混声启用

&lt;img src=&quot;../images/声音设置3.png&quot; alt=&quot;&quot; width=&quot;400px&quot; /&gt;

这时候再执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ffmpeg -list_devices true -f dshow -i dummy&lt;/code&gt; 输出为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ffmpeg version 7.1.1-full_build-www.gyan.dev Copyright (c) 2000-2025 the FFmpeg developers
  built with gcc 14.2.0 (Rev1, Built by MSYS2 project)
  configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-lcms2 --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-libdvdnav --enable-libdvdread --enable-sdl2 --enable-libaribb24 --enable-libaribcaption --enable-libdav1d --enable-libdavs2 --enable-libopenjpeg --enable-libquirc --enable-libuavs3d --enable-libxevd --enable-libzvbi --enable-libqrencode --enable-librav1e --enable-libsvtav1 --enable-libvvenc --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxeve --enable-libxvid --enable-libaom --enable-libjxl --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-dxva2 --enable-d3d11va --enable-d3d12va --enable-ffnvcodec --enable-libvpl --enable-nvdec --enable-nvenc --enable-vaapi --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libcodec2 --enable-libilbc --enable-libgsm --enable-liblc3 --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
  libavutil      59. 39.100 / 59. 39.100
  libavcodec     61. 19.101 / 61. 19.101
  libavformat    61.  7.100 / 61.  7.100
  libavdevice    61.  3.100 / 61.  3.100
  libavfilter    10.  4.100 / 10.  4.100
  libswscale      8.  3.100 /  8.  3.100
  libswresample   5.  3.100 /  5.  3.100
  libpostproc    58.  3.100 / 58.  3.100
[dshow @ 0000020942ff6cc0] &quot;Integrated Camera&quot; (video)
[dshow @ 0000020942ff6cc0]   Alternative name &quot;@device_pnp_\\?\usb#vid_13d3&amp;amp;pid_5419&amp;amp;mi_00#7&amp;amp;17d116b8&amp;amp;1&amp;amp;0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global&quot;
[dshow @ 0000020942ff6cc0] &quot;麦克风阵列 (Realtek(R) Audio)&quot; (audio)
[dshow @ 0000020942ff6cc0]   Alternative name &quot;@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{253B9838-6E9C-47DB-A420-848E63B3931C}&quot;
[dshow @ 0000020942ff6cc0] &quot;立体声混音 (Realtek(R) Audio)&quot; (audio)
[dshow @ 0000020942ff6cc0]   Alternative name &quot;@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{A04F0465-843E-4E64-891D-31A28192D215}&quot;
[in#0 @ 0000020942fdd340] Error opening input: Immediate exit requested
Error opening input file dummy.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

可以看到有三个设备：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Integrated Camera&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;麦克风阵列 (Realtek(R) Audio)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;立体声混音 (Realtek(R) Audio)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

当然，也可以安装开源项目 &lt;a href=&quot;https://github.com/rdp/screen-capture-recorder-to-video-windows-free&quot;&gt;rdp/screen-capture-recorder-to-video-windows-free&lt;/a&gt;，
安装完成后，`` 命令输出如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ffmpeg version 7.1.1-full_build-www.gyan.dev Copyright (c) 2000-2025 the FFmpeg developers
  built with gcc 14.2.0 (Rev1, Built by MSYS2 project)
  configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-lcms2 --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-libdvdnav --enable-libdvdread --enable-sdl2 --enable-libaribb24 --enable-libaribcaption --enable-libdav1d --enable-libdavs2 --enable-libopenjpeg --enable-libquirc --enable-libuavs3d --enable-libxevd --enable-libzvbi --enable-libqrencode --enable-librav1e --enable-libsvtav1 --enable-libvvenc --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxeve --enable-libxvid --enable-libaom --enable-libjxl --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-dxva2 --enable-d3d11va --enable-d3d12va --enable-ffnvcodec --enable-libvpl --enable-nvdec --enable-nvenc --enable-vaapi --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libcodec2 --enable-libilbc --enable-libgsm --enable-liblc3 --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
  libavutil      59. 39.100 / 59. 39.100
  libavcodec     61. 19.101 / 61. 19.101
  libavformat    61.  7.100 / 61.  7.100
  libavdevice    61.  3.100 / 61.  3.100
  libavfilter    10.  4.100 / 10.  4.100
  libswscale      8.  3.100 /  8.  3.100
  libswresample   5.  3.100 /  5.  3.100
  libpostproc    58.  3.100 / 58.  3.100
[dshow @ 0000020d0d8f6d40] &quot;Integrated Camera&quot; (video)
[dshow @ 0000020d0d8f6d40]   Alternative name &quot;@device_pnp_\\?\usb#vid_13d3&amp;amp;pid_5419&amp;amp;mi_00#7&amp;amp;17d116b8&amp;amp;1&amp;amp;0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global&quot;
[dshow @ 0000020d0d8f6d40] &quot;screen-capture-recorder&quot; (video)
[dshow @ 0000020d0d8f6d40]   Alternative name &quot;@device_sw_{860BB310-5D01-11D0-BD3B-00A0C911CE86}\{4EA69364-2C8A-4AE6-A561-56E4B5044439}&quot;
[dshow @ 0000020d0d8f6d40] &quot;立体声混音 (Realtek(R) Audio)&quot; (audio)
[dshow @ 0000020d0d8f6d40]   Alternative name &quot;@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{A04F0465-843E-4E64-891D-31A28192D215}&quot;
[dshow @ 0000020d0d8f6d40] &quot;virtual-audio-capturer&quot; (audio)
[dshow @ 0000020d0d8f6d40]   Alternative name &quot;@device_sw_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\{8E146464-DB61-4309-AFA1-3578E927E935}&quot;
[dshow @ 0000020d0d8f6d40] &quot;麦克风阵列 (Realtek(R) Audio)&quot; (audio)
[dshow @ 0000020d0d8f6d40]   Alternative name &quot;@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{253B9838-6E9C-47DB-A420-848E63B3931C}&quot;
[in#0 @ 0000020d0d8dd380] Error opening input: Immediate exit requested
Error opening input file dummy.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此时多出了两个设备：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screen-capture-recorder&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virtual-audio-capturer&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;仅录制屏幕&quot;&gt;仅录制屏幕&lt;/h2&gt;

如果仅仅需要录制桌面，而不需要录制摄像头和声音，可以使用如下配置：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;record-screen&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;ffmpeg&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;argvs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-f&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;gdigrab&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-i&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;desktop&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-pix_fmt&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;yuv420p&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-f&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;mp4&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;录制屏幕麦克风扬声器&quot;&gt;录制屏幕、麦克风、扬声器&lt;/h2&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;record-screen&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;ffmpeg&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;argvs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-f&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;dshow&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-i&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;audio=麦克风阵列 (Realtek(R) Audio)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-f&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;dshow&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-i&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;audio=立体声混音 (Realtek(R) Audio)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-filter_complex&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;amix=inputs=2:duration=first:dropout_transition=2&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-f&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;gdigrab&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-r&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;60&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-draw_mouse&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-i&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;desktop&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-pix_fmt&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;yuv420p&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-f&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;mp4&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

录制视频时，偶尔会遇到类似于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;real-time buffer frame dropped&lt;/code&gt; 这样的错误提示，
参考&lt;a href=&quot;https://github.com/rdp/screen-capture-recorder-to-video-windows-free/issues/136&quot;&gt;issue 136&lt;/a&gt;
提到的解决方案，增加参数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-rtbufsize 1500M&lt;/code&gt;

&lt;h2 id=&quot;安装配置&quot;&gt;安装配置&lt;/h2&gt;

使用 &lt;a href=&quot;https://github.com/wsdjeg/nvim-plug&quot;&gt;nvim-plug&lt;/a&gt; 插件管理器：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/record-key.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cmds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;RecordKeyToggle&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;config_before&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;leader&amp;gt;rk&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;cmd&amp;gt;RecordKeyToggle&amp;lt;cr&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;silent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/record-screen.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;depends&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/job.nvim&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/notify.nvim&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plugins.record-screen&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

插件详细配置参考文件 &lt;a href=&quot;https://github.com/wsdjeg/nvim-config/blob/master/lua/plugins/record-screen.lua&quot;&gt;nvim-config/lua/plugins/record-screen.lua&lt;/a&gt;

通过这个配置文件，我新建了一个用户自定义命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:RecordScreen&lt;/code&gt;，支持如下参数：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-camera&lt;/code&gt;: 录制摄像头&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-speaker&lt;/code&gt;: 录制扬声器&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--microphone&lt;/code&gt;: 录制麦克风&lt;/li&gt;
&lt;/ul&gt;

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:RecordScreen stop&lt;/code&gt; 停止录屏。

&lt;h2 id=&quot;参考阅读&quot;&gt;参考阅读&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://newzone.top/posts/2022-11-03-ffmpeg_screen_recording.html&quot;&gt;抛弃又贵又难用的录屏软件，3 分钟入门 FFmpeg&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 12 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-record-key-and-screen/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-record-key-and-screen/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 自动切换至项目根目录</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#安装-rooternvim&quot; id=&quot;markdown-toc-安装-rooternvim&quot;&gt;安装 rooter.nvim&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#插件配置&quot; id=&quot;markdown-toc-插件配置&quot;&gt;插件配置&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#telescope-拓展&quot; id=&quot;markdown-toc-telescope-拓展&quot;&gt;Telescope 拓展&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#插件运行日志&quot; id=&quot;markdown-toc-插件运行日志&quot;&gt;插件运行日志&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#设置-callback-函数&quot; id=&quot;markdown-toc-设置-callback-函数&quot;&gt;设置 callback 函数&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

在使用 Neovim 打开某个文件时，我希望 Neovim 自动把当前目录切换到该文件所在的项目根目录。
其实，能实现这一功能的有不少的插件，我最早使用的是 vim-rooter，但是后来因为切换到了 Neovim，
因此使用 Lua 重写了该功能，这个功能早期是 SpaceVim 的内置的，
在 SpaceVim 项目停止维护后独立成单独的插件：&lt;a href=&quot;https://github.com/wsdjeg/rooter.nvim&quot;&gt;rooter.nvim&lt;/a&gt;。

&lt;h2 id=&quot;安装-rooternvim&quot;&gt;安装 rooter.nvim&lt;/h2&gt;

可以使用任意插件管理器进行安装，比如 &lt;a href=&quot;https://github.com/wsdjeg/nvim-plug&quot;&gt;nvim-plug&lt;/a&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/rooter.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;rooter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;插件配置&quot;&gt;插件配置&lt;/h2&gt;

以下是默认的配置：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;rooter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;root_patterns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;.git/&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;outermost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;enable_cache&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;project_non_root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;-- this can be &apos;&apos;, &apos;home&apos; or &apos;current&apos;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;enable_logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;-- enable runtime log via logger.nvim&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project_non_root&lt;/code&gt;: 配置打开非项目文件时的行为&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;outermost&lt;/code&gt;: 若设为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;，那么通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root_patterns&lt;/code&gt; 检索到的多个目录时，取最外层目录。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;telescope-拓展&quot;&gt;Telescope 拓展&lt;/h2&gt;

rooter.nvim 自带 telescope.nvim 拓展，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Telescope project&lt;/code&gt; 列出过往打开过的项目。

&lt;img src=&quot;../images/telescope-project.png&quot; alt=&quot;telescope project&quot; /&gt;

&lt;h2 id=&quot;插件运行日志&quot;&gt;插件运行日志&lt;/h2&gt;

在插件运行过程中产生的日志信息，可以使用 &lt;a href=&quot;https://github.com/wsdjeg/logger.nvim&quot;&gt;logger.nvim&lt;/a&gt; 进行查看。
如果有这一需求，那么在安装 rooter.nvim 时，需要添加相应的依赖插件。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/rooter.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;rooter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;depends&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/logger.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;设置-callback-函数&quot;&gt;设置 callback 函数&lt;/h2&gt;

通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reg_callback&lt;/code&gt; 可以设置 callback 函数，该函数会在项目切换时被调用。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;update_ctags_option&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;project_root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getcwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;util&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unify_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;tags&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cache_dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
        &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;util&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_to_fname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;project_root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/tags&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;table.concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;,&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;rooter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reg_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update_gtags_option&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sat, 22 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-project-root-manager/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-project-root-manager/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 日志插件 logger.nvim</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#安装&quot; id=&quot;markdown-toc-安装&quot;&gt;安装&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#在插件中使用&quot; id=&quot;markdown-toc-在插件中使用&quot;&gt;在插件中使用&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;logger.nvim&lt;/code&gt; 提供了一个基础的日志框架，不同的插件可以共用一个日志系统。

&lt;h2 id=&quot;安装&quot;&gt;安装&lt;/h2&gt;

和安装其他插件一样，可以使用&lt;a href=&quot;https://github.com/wsdjeg/nvim-plug&quot;&gt;nvim-plug&lt;/a&gt;安装：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/logger.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;logger&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;-- the level only can be:&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;-- 0 : log debug, info, warn, error messages&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;-- 1 : log info, warn, error messages&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;-- 2 : log warn, error messages&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;-- 3 : log error messages&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;在插件中使用&quot;&gt;在插件中使用&lt;/h2&gt;

比如新建了一个插件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fyz.nvim&lt;/code&gt;，此时可以添加一个文件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lua/fyz/log.lua&lt;/code&gt;:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;pcall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;logger&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;fyz&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;hello world&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;hello world&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在自己的插件中就可以使用：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;fyz.log&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;this is log from fyz.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;logger.viewRuntimeLog()&lt;/code&gt; 查看所有的日志输出，其中就会有如下一行：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[     fyz ] [23:22:50:576] [ Info  ] this is log from fyz.nvim

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 16 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-logger/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-logger/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 任务管理插件 tasks.nvim</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#安装及配置-tasksnvim&quot; id=&quot;markdown-toc-安装及配置-tasksnvim&quot;&gt;安装及配置 tasks.nvim&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#常用命令&quot; id=&quot;markdown-toc-常用命令&quot;&gt;常用命令&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

关于任务（Tasks）管理，实际上早在 2020 年的时候就已经给 SpaceVim &lt;a href=&quot;https://github.com/wsdjeg/SpaceVim/pull/3346&quot;&gt;增加了 Tasks 支持&lt;/a&gt;，参考的是 Vscode Tasks Manager 的实现。
最早的版本使用 Vim Script 实现的，大约在 2023 年的时候&lt;a href=&quot;https://github.com/wsdjeg/SpaceVim/commit/2b2c2aa5f6e812f8020bb53d001cc97c09a53b4f&quot;&gt;增加了 Lua 实现版本&lt;/a&gt;，
不过这些都是在 SpaceVim 内置的插件。

现在，SpaceVim 已经不再维护，而这些常用的功能，我也会陆续剥离出来单独形成插件，这篇文章主要介绍 &lt;a href=&quot;https://github.com/wsdjeg/tasks.nvim&quot;&gt;tasks.nvim&lt;/a&gt;

&lt;h2 id=&quot;安装及配置-tasksnvim&quot;&gt;安装及配置 tasks.nvim&lt;/h2&gt;

可以使用任意插件管理器进行安装，这里以 nvim-plug 为例：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/tasks.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;depends&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/code-runner.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;tasks&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;global_tasks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;~/.tasks.toml&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;local_tasks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;.tasks.toml&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;npm&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;常用命令&quot;&gt;常用命令&lt;/h2&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tasks.nvim&lt;/code&gt; 提供了三个常用命令：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:TasksEdit&lt;/code&gt;：用于打开 tasks 配置文件，默认打开的是项目配置文件，加上感叹号（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:TasksEdit!&lt;/code&gt;）则打开全局配置文件。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:TasksList&lt;/code&gt;：使用分屏列出所有 tasks&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:TasksSelect&lt;/code&gt;：选择某个 task 并执行&lt;/li&gt;
&lt;/ul&gt;

当然，如果你也安装了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;telescope.nvim&lt;/code&gt; 那么，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Telescope tasks&lt;/code&gt; 模糊搜索可用的 tasks.
</description>
        <pubDate>Sat, 01 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/tasks-manager-for-neovim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/tasks-manager-for-neovim/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 代码执行插件 code-runner.nvim</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#安装及配置&quot; id=&quot;markdown-toc-安装及配置&quot;&gt;安装及配置&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#自动更新-runner-参数&quot; id=&quot;markdown-toc-自动更新-runner-参数&quot;&gt;自动更新 runner 参数&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

Vscode 有一个非常出名的插件，叫做 &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=formulahendry.code-runner&quot;&gt;Code Runner&lt;/a&gt;，我曾经也给 SpaceVim 添加了这么一个功能。

现在将这一功能剥离出来形成一个单独独立的 neovim 插件：&lt;a href=&quot;https://github.com/wsdjeg/code-runner.nvim&quot;&gt;code-runner.nvim&lt;/a&gt;

&lt;h2 id=&quot;安装及配置&quot;&gt;安装及配置&lt;/h2&gt;

可以使用任意插件管理器进行安装，这里以 nvim-plug 为例：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/code-runner.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;code-runner&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;lua&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;lua&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usestdin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;enter_win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;自动更新-runner-参数&quot;&gt;自动更新 runner 参数&lt;/h2&gt;

借助 &lt;a href=&quot;https://github.com/wsdjeg/rooter.nvim&quot;&gt;rooter.nvim&lt;/a&gt; 插件，可以在切换项目时，读取 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.clang&lt;/code&gt; 文件内容，并且更新 c 语言的 runner。具体代码实现：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_runner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;exe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;gcc&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;targetopt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-o&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;usestdin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-std=c11&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-xc&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;code-runner&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;#TEMP#&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;leader&amp;gt;lr&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;cmd&amp;gt;lua require(&quot;code-runner&quot;).open()&amp;lt;cr&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;silent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- make sure rooter.nvim plugin is loaded before code-runner&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;update_clang_flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filereadable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;.clang&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;.clang&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-std=c11&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-xc&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;c_runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;rooter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reg_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update_clang_flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 28 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-code-runner/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-code-runner/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 插件管理器 nvim-plug</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#项目简介&quot; id=&quot;markdown-toc-项目简介&quot;&gt;项目简介&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#功能特点&quot; id=&quot;markdown-toc-功能特点&quot;&gt;功能特点&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#完全异步调用命令&quot; id=&quot;markdown-toc-完全异步调用命令&quot;&gt;完全异步调用命令&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#支持多种懒加载模式&quot; id=&quot;markdown-toc-支持多种懒加载模式&quot;&gt;支持多种懒加载模式&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#ui-是可替换的&quot; id=&quot;markdown-toc-ui-是可替换的&quot;&gt;UI 是可替换的&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#支持多种插件类型&quot; id=&quot;markdown-toc-支持多种插件类型&quot;&gt;支持多种插件类型&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#安装方式&quot; id=&quot;markdown-toc-安装方式&quot;&gt;安装方式&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#自动安装推荐&quot; id=&quot;markdown-toc-自动安装推荐&quot;&gt;自动安装（推荐）&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#使用-luarocks&quot; id=&quot;markdown-toc-使用-luarocks&quot;&gt;使用 LuaRocks&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#基本配置&quot; id=&quot;markdown-toc-基本配置&quot;&gt;基本配置&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#添加插件&quot; id=&quot;markdown-toc-添加插件&quot;&gt;添加插件&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#常用命令&quot; id=&quot;markdown-toc-常用命令&quot;&gt;常用命令&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

如果你也喜欢折腾 Neovim ，可能也会在插件管理器上花不少时间吧。
我从最早的 vundle（Bundle）、plug.vim，到后来的 neobundle.vim、dein.nvim，都使用很长一段时间。
使用最长时间的要算 dein.nvim，这是一个无 UI 界面的插件管理器，我甚至曾经还为该插件写过一个 dein-ui.vim 模仿 plug.vim 的界面。

我写 &lt;a href=&quot;https://github.com/wsdjeg/nvim-plug&quot;&gt;nvim-plug&lt;/a&gt; 的原因其实很简单，我前面写过一篇插件管理器的运行机制&lt;a href=&quot;https://wsdjeg.net/the-implementation-logic-of-plugin-manager/&quot;&gt;《Neovim 和 Vim 插件管理器的实现逻辑》&lt;/a&gt; 。

&lt;blockquote&gt;
  我想练习一下插件管理器的实现，之前看过 dein.nvim 的一些源码，里面的懒加载实现感觉很有趣。
我想要一个完全可控、异步、并且不限制 UI 表现形式的插件管理器。
&lt;/blockquote&gt;

项目地址: &lt;a href=&quot;https://github.com/wsdjeg/nvim-plug&quot;&gt;wsdjeg/nvim-plug&lt;/a&gt;

&lt;img src=&quot;../images/nvim-plug.gif&quot; alt=&quot;nvim-plug&quot; /&gt;

&lt;h2 id=&quot;项目简介&quot;&gt;项目简介&lt;/h2&gt;

nvim-plug 是一个用 Lua 编写的 Neovim 插件管理器，核心目标是：

&lt;ul&gt;
  &lt;li&gt;插件安装和更新必须是异步的&lt;/li&gt;
  &lt;li&gt;插件管理过程和 UI 界面分离&lt;/li&gt;
  &lt;li&gt;支持常用的插件懒加载模式&lt;/li&gt;
&lt;/ul&gt;

插件描述规范这一块我主要参考了 dein.nvim，之前用的比较多，也习惯了一些 key 值叫法和意义。

&lt;h2 id=&quot;功能特点&quot;&gt;功能特点&lt;/h2&gt;

&lt;h3 id=&quot;完全异步调用命令&quot;&gt;完全异步调用命令&lt;/h3&gt;

所有插件的 clone、pull、build 都是通过 job.nvim 并发执行的，
不会出现卡在安装界面不能操作的情况。你可以根据网络和机器性能自由设置并行任务数量。

&lt;h3 id=&quot;支持多种懒加载模式&quot;&gt;支持多种懒加载模式&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;事件: events&lt;/li&gt;
  &lt;li&gt;命令: cmds&lt;/li&gt;
  &lt;li&gt;文件类型: on_ft&lt;/li&gt;
  &lt;li&gt;按键: on_map&lt;/li&gt;
  &lt;li&gt;Vim 函数: on_func&lt;/li&gt;
&lt;/ul&gt;

插件什么时候加载，完全可以在配置文件里面明确，而不需要一堆额外逻辑拼出来。

&lt;h3 id=&quot;ui-是可替换的&quot;&gt;UI 是可替换的&lt;/h3&gt;

nvim-plug 并不假设你一定要用某种 UI：

&lt;ul&gt;
  &lt;li&gt;默认是分屏 UI，参考的是 vundle.vim&lt;/li&gt;
  &lt;li&gt;可以切换为 notify 风格的浮动通知&lt;/li&gt;
  &lt;li&gt;也可以完全自己实现 UI 回调&lt;/li&gt;
&lt;/ul&gt;

插件管理器只负责状态，展示方式由你决定。

&lt;h3 id=&quot;支持多种插件类型&quot;&gt;支持多种插件类型&lt;/h3&gt;

除了 Git 仓库，还支持：

&lt;ul&gt;
  &lt;li&gt;raw 脚本&lt;/li&gt;
  &lt;li&gt;LuaRocks 包&lt;/li&gt;
  &lt;li&gt;本地开发路径&lt;/li&gt;
&lt;/ul&gt;

一些“不是标准插件，但又需要被管理的仓库”也可以统一处理。

我甚至使用这个插件管理器，管理一些上游的 GitHub 仓库（非插件），我需要定期同步到本地某个指定的位置，方便本地阅读代码。

&lt;h2 id=&quot;安装方式&quot;&gt;安装方式&lt;/h2&gt;

&lt;h3 id=&quot;自动安装推荐&quot;&gt;自动安装（推荐）&lt;/h3&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;data&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/repos/&apos;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bootstrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isdirectory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&apos;git&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&apos;clone&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&apos;--depth&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&apos;https://github.com/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;.git&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runtimepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;bootstrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/job.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;bootstrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/logger.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;bootstrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/nvim-plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;使用-luarocks&quot;&gt;使用 LuaRocks&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;luarocks &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;nvim-plug
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;基本配置&quot;&gt;基本配置&lt;/h2&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;bundle_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;data&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/repos&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;raw_plugin_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;data&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/repos/raw_plugin&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;max_processes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;base_url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;https://github.com&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ui&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;default&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;clone_depth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;添加插件&quot;&gt;添加插件&lt;/h2&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/scrollbar.vim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;events&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;VimEnter&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/flygrep.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cmds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;FlyGrep&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;flygrep&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;raw&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;https://gist.githubusercontent.com/.../markdown.vim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;script_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;after/syntax&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;常用命令&quot;&gt;常用命令&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Plug install&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Plug update&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 09 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-plugin-manager-nvim-plug/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-plugin-manager-nvim-plug/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>从 VimScipt 切换至 Lua</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#为什么选择-lua&quot; id=&quot;markdown-toc-为什么选择-lua&quot;&gt;为什么选择 Lua&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#学习-lua&quot; id=&quot;markdown-toc-学习-lua&quot;&gt;学习 Lua&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#配置文件结构&quot; id=&quot;markdown-toc-配置文件结构&quot;&gt;配置文件结构&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#初始化文件&quot; id=&quot;markdown-toc-初始化文件&quot;&gt;初始化文件&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#ftplugin&quot; id=&quot;markdown-toc-ftplugin&quot;&gt;ftplugin&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#options&quot; id=&quot;markdown-toc-options&quot;&gt;Options&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#事件自动命令&quot; id=&quot;markdown-toc-事件自动命令&quot;&gt;事件自动命令&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#用户自定义命令&quot; id=&quot;markdown-toc-用户自定义命令&quot;&gt;用户自定义命令&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#设置快捷键&quot; id=&quot;markdown-toc-设置快捷键&quot;&gt;设置快捷键&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#变量类型转换&quot; id=&quot;markdown-toc-变量类型转换&quot;&gt;变量类型转换&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#vimg-访问全局变量的弊端&quot; id=&quot;markdown-toc-vimg-访问全局变量的弊端&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.g&lt;/code&gt; 访问全局变量的弊端&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

Lua 在 Neovim 中已经被当作了一等公民，目前火热的 Neovim 插件、配置基本上都是使用 Lua 来开发的。而我也是从 2016 年就开始使用 Neovim 了。
这篇文章整理了一些从 VimScript 切换到 Lua 配置一些 Tips。

本文写作环境：

&lt;ul&gt;
  &lt;li&gt;OS：Windows 11&lt;/li&gt;
  &lt;li&gt;Neovim：v0.10.0&lt;/li&gt;
  &lt;li&gt;Terminal: Windows Terminal&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;为什么选择-lua&quot;&gt;为什么选择 Lua&lt;/h2&gt;

在前面我写过两篇文字，主要是来比较 Lua（luajit）与 VimScipt 以及 Vim9Script 的运行速度。

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://wsdjeg.net/speed-comparison-between-vim9script-and-lua/&quot;&gt;Vim9Script 与 Lua 的速度比较&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wsdjeg.net/rewrite-spacevim-builtin-plugin-using-lua/&quot;&gt;使用 Lua 重写 SpaceVim 内置插件&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

比较的结果显而易见，Luajit 的速度比起 VimScipt 以及 Vim9Script 快很多，而我的配置还是比较重的，因此选择 Lua 将会大大提升使用体验。

&lt;h3 id=&quot;学习-lua&quot;&gt;学习 Lua&lt;/h3&gt;

Lua 是一门语法非常简单的编程语言，可以查看&lt;a href=&quot;https://wsdjeg.net/learn-lua-script/&quot;&gt;《学习 Lua 脚本语言》&lt;/a&gt;。

&lt;h2 id=&quot;配置文件结构&quot;&gt;配置文件结构&lt;/h2&gt;

&lt;h3 id=&quot;初始化文件&quot;&gt;初始化文件&lt;/h3&gt;

Neovim 的初始化文件是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~\AppData\Local\nvim\init.lua&lt;/code&gt;，Linux 系统是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/nvim/init.lua&lt;/code&gt;。Neovim 启动时会自动读取并执行该文件内容。

&lt;h3 id=&quot;ftplugin&quot;&gt;ftplugin&lt;/h3&gt;

当打开一个文件，Neovim 通常会自动识别文件类型并且自动设定 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filetype&lt;/code&gt; 。比如，打开 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Test.java&lt;/code&gt; 文件，此时 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ftplugin/java.lua&lt;/code&gt; 就会被调用执行。

&lt;h2 id=&quot;options&quot;&gt;Options&lt;/h2&gt;

Neovim 提供了多种方式设置 Neovim Option。

&lt;strong&gt;使用 Neovim API：&lt;/strong&gt;

Neovim 提供了设置 Option 的 API 函数：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_set_option_value({name}, {value}, {opts})&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opts&lt;/code&gt; 是一个 Lua table，支持的 key 包括：

&lt;ul&gt;
  &lt;li&gt;scope：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grobal&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;local&lt;/code&gt;，类似于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:setglobal&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:setlocal&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;win: 设置指定 window-ID 的 local option&lt;/li&gt;
  &lt;li&gt;buf：设置指定 buffer number 的 local option&lt;/li&gt;
&lt;/ul&gt;

&lt;strong&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.o&lt;/code&gt;：&lt;/strong&gt;

这类似于直接使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set&lt;/code&gt; 命令，默认是设置 global option。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;-- 禁用行号，启用行号可以设置为 true&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;relativenumber&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- 禁用相对行号&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;strong&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.bo&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.wo&lt;/code&gt;：&lt;/strong&gt;

这类似于使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:setlocal&lt;/code&gt; 命令，但是还是有些区别的，按照 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h vim.bo&lt;/code&gt; 描述，其使用的格式是：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.bo[{bufnr}].opt_name&lt;/code&gt;，
如果设置的 option 不是 local to buffer 就会报错，比如执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:lua vim.bo.number = true&lt;/code&gt; 就会报错：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;E5108: Error executing lua [string &quot;:lua&quot;]:1: &apos;buf&apos; cannot be passed for window-local option &apos;number&apos;
stack traceback:
	[C]: in function &apos;__newindex&apos;
	[string &quot;:lua&quot;]:1: in main chunk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

同理，使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.wo&lt;/code&gt; 时也会有类似的问题，因此在使用这两个方式设置 option 时，需要判断 option 是 local to window 还是 local to buffer, 一般在 help 文档里面都有。
比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;number&apos;&lt;/code&gt;:

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&apos;number&apos; &apos;nu&apos;		boolean	(default off)
			local to window
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当然，Vim 也提供了函数去判断，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_get_option_info2({name}, {opts})&lt;/code&gt; 返回值是一个 lua table，其中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scope&lt;/code&gt; key 值就可以用来判断，其值可以是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;win&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buf&lt;/code&gt;。

实际上，如果去看 Neovim 的源码，你会发现不管是 vim.o 还是 vim.bo 等 只不是 API 的 wrap 而已：

&lt;a href=&quot;https://github.com/neovim/neovim/blob/master/runtime/lua/vim/_options.lua#L242&quot;&gt;neovim’s options.lua#L242&lt;/a&gt;:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;setmetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;__index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_option_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;__newindex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_set_option_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

因此，如果需要的话，也可以自己设置一个新的函数批量设置 option, 比如，某个插件打开了一个浮窗，浮窗内是对应的插件 buffer。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;set_local&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bufnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_option_info2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scope&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;win&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_set_option_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;winid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_get_option_info2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scope&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;buf&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_set_option_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bufnr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;-- skip global opt&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bufnr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_plugin_float_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;set_local&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bufnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;relativenumber&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;filetype&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;java&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;bufhidden&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;wipe&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;事件自动命令&quot;&gt;事件自动命令&lt;/h2&gt;

使用 VimScipt 定义自动命令（autocmd）的时候，通常我们可以这样写：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;augroup test_augroup_vim
  autocmd&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;
  autocmd &lt;span class=&quot;nb&quot;&gt;WinEnter&lt;/span&gt; * &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:test1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  autocmd &lt;span class=&quot;nb&quot;&gt;WinEnter&lt;/span&gt; * &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:test2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
augroup END
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此时，如果需要清除上述两个自动命令的其中一个，就无法实现。只能使用如下脚本全部清除：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;augroup text_augroup_vim
  autocmd&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;
augroup END
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

而 Neovim 提供了两个函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_create_autocmd&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_del_autocmd&lt;/code&gt;，演示如下：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;test_augroup_neovim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;autocmd_id1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;WinEnter&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;autocmd_id2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;WinEnter&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此时如果需要删除第二个自动命令，只需要：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_del_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;autocmd_id2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;用户自定义命令&quot;&gt;用户自定义命令&lt;/h2&gt;

可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.api.nvim_create_user_command({name}, {command}, {opts})&lt;/code&gt; API 来新建命令。

这个 API 函数接受三个参数，第一个顾名思义就是新建的命令的具体名称，
第二个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;command&lt;/code&gt; 可以是一个 string 也可以是一个 lua function。如果是 string，
当执行这个命令时，这段字符串会被直接执行。如果是 Lua function，则会被传入一个 table 参数调用。
第三个参数是设定命令的一些参数，类似于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h command-attributes&lt;/code&gt;

比如：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_user_command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;SayHello&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;hello&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;bang&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在上述函数内，参数 opt 是一个 Lua table，key 值包括：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{ &quot;bang&quot;, &quot;reg&quot;, &quot;range&quot;, &quot;args&quot;, &quot;mods&quot;, &quot;line1&quot;, &quot;smods&quot;, &quot;fargs&quot;, &quot;line2&quot;, &quot;count&quot;, &quot;name&quot; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;strong&gt;bang:&lt;/strong&gt;

如果定义命令时，第三个参数 bang = true，那么可以在执行命令时带上感叹号。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_user_command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Test&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bang&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;bang&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上述定义的命令，执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Test&lt;/code&gt; 时打印 false，执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Test!&lt;/code&gt; 时打印 true，也可以在函数内判断 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if opt.bang&lt;/code&gt; 为命令是否带感叹号赋予不一样的意义。

有一些插件的命令支持两个感叹号，是如何实现的呢？比如 &lt;a href=&quot;https://github.com/lambdalisue/vim-gina&quot;&gt;vim-gina&lt;/a&gt;

Single command. Users do not need to remember tons of commands

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Gina {command}&lt;/code&gt; will execute a gina command or a git raw command asynchronously&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Gina! {command}&lt;/code&gt; will execute a git raw command asynchronously&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Gina!! {command}&lt;/code&gt; will execute a git raw command in a shell (mainly for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Gina!! add -p&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Gina!! rebase -i&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

下面是简单的实现代码：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_user_command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Gina&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bang&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;it is Gina&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bang&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;!&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;it is Gina!!&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;it is Gina!&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;bang&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

nargs 可以设置为 0、1、’*‘、’?’、’+’ 五种。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_user_command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Test1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_user_command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Test2&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_user_command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Test3&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_user_command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Test4&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;+&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_user_command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Test5&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;?&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

nargs 为 0，执行命令如果带上参数，那么就会报错。比如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Test1 foo&lt;/code&gt; 报错 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E488: Trailing characters: foo&lt;/code&gt;。

nargs 为 1 时，如果执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Test2 foo zaa xss&lt;/code&gt; 就会发现输出内容为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;foo zaa xss
{ &quot;foo zaa xss&quot; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

意味着，如果设置为 1，执行命令的后面一整串字符串不管是否有空格间隔，都被当作为一个参数。

nargs 为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; 时，如果执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Test3 foo zaa xss&lt;/code&gt; 就会发现输出内容为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;foo zaa xss
{ &quot;foo&quot;, &quot;zaa&quot;, &quot;xss&quot; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

可以看出，args 还是整个字符串，但是 fargs 则是一个列表，包含了三个参数

nargs 为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; 时，如果执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Test4 foo zaa xss&lt;/code&gt; 就会发现输出内容为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;foo zaa xss
{ &quot;foo&quot;, &quot;zaa&quot;, &quot;xss&quot; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

不同的是，如果执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Test4&lt;/code&gt; 不带参数，则会报错：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E471: Argument required&lt;/code&gt;

nargs 为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt; 时，如果执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Test5 foo zaa xss&lt;/code&gt; 就会发现输出内容为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;foo zaa xss
{ &quot;foo zaa xss&quot; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

与设置成 1 不同的是，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Test5&lt;/code&gt; 可以不带参数直接执行

&lt;h2 id=&quot;设置快捷键&quot;&gt;设置快捷键&lt;/h2&gt;

Neovim &lt;a href=&quot;https://github.com/neovim/neovim/commit/6d41f65aa45f10a93ad476db01413abaac21f27d&quot;&gt;提供了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.keymap.set()&lt;/code&gt; 函数&lt;/a&gt;来设置快捷键，
如果阅读源码的话，也可以发现，实际上这个函数也不过是包装了 Neovim API 函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.api.nvim_buf_set_keymap&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.api.nvim_set_keymap&lt;/code&gt;。

但是原生的 API &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_set_keymap&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_buf_set_keymap&lt;/code&gt; 使用起来太麻烦了，对于一些特殊按键还需要使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_replace_termcodes()&lt;/code&gt; 去转换。

而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.keymap.set({mode}, {lhs}, {rhs}, {opts})&lt;/code&gt; 的优势是：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;differences compared to regular set_keymap:
- remap is used as opposite of noremap. By default it&apos;s true for &amp;lt;Plug&amp;gt; keymaps and false for others.
- rhs can be lua function.
- mode can be a list of modes.
- replace_keycodes option for lua function expr maps. (Default: true)
- handles buffer specific keymaps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这个 &lt;a href=&quot;https://github.com/neovim/neovim/commit/c031e038df8429e14b0aa608aaa77068daa680f0&quot;&gt;commit&lt;/a&gt; 移除了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Plug&amp;gt; kemaps&lt;/code&gt; 检测, 这里是与 Vim 不一致的地方。

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/neovim/neovim/pull/16969&quot;&gt;feat: ignore nore on &amp;lt;Plug&amp;gt; maps&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/neovim/neovim/pull/16591&quot;&gt;feat(lua): add support for lua keymaps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;i&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;Esc&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;noautocmd stopinsert&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prompt_winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompt_bufid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;变量类型转换&quot;&gt;变量类型转换&lt;/h2&gt;

不管是从 Lua 到 VimScipt 还是从 VimScipt 到 Lua，变量类型转换是都是创建了一个副本，副本做的修改，通常无法在原变量上体现。
这也是我尽量避免使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.fn&lt;/code&gt; 原因。

比如以下这段 VimScipt：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s:a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
echo &lt;span class=&quot;nv&quot;&gt;s:a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上输出是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1, 2, 3]&lt;/code&gt;。

换成 Lua：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;--- 输出是 {1, 2}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

看一下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.fn&lt;/code&gt; 的源码：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;c1&quot;&gt;-- vim.fn.{func}(...)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;---@nodoc&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;setmetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;--- @param t table&amp;lt;string,function&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;--- @param key string&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;--- @return function&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;__index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_fn&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;--- @type function&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_fn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Tried to call API function with vim.fn: use vim.api.%s instead&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_fn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_fn&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_fn&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

实际上就是调用的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.call(key, ...)&lt;/code&gt;

因此应当尽量避免使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.fn&lt;/code&gt; 调用 VimScipt 函数操作 Lua 变量，前面的示例应该改为：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;--- 输出是 {1, 2, 3}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;vimg-访问全局变量的弊端&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.g&lt;/code&gt; 访问全局变量的弊端&lt;/h2&gt;

如果看了 &lt;a href=&quot;https://github.com//neovim/neovim/blob/d3e495ce03e3389c2c28ffcfe2e41c088a37f1ef/runtime/lua/vim/_editor.lua#L505&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.g&lt;/code&gt; 的源码&lt;/a&gt;，
不难发现，实际上是通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim._getvar&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim._setvar&lt;/code&gt; 来分别映射 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__index&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__newindex&lt;/code&gt;。

可以理解为，每一次访问 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__index&lt;/code&gt; 时，调用一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim._getvar&lt;/code&gt; 获取 viml 变量，并转化为一个新的 Lua 变量。最简单的测试：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:wsd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;a&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;a&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wsd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wsd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 执行两次，打印的结果不一样&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- table: 0x0215fa040d28&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- table: 0x0215fb557f10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这就意味着，如果 VimL 字典变量发生了内部变化，之前转化的 Lua 变量并不会发生变化：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;[[
let g:wsd = {&apos;a&apos; : &apos;a&apos;}
]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wsd&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;[[
let g:wsd.a = &apos;b&apos;
]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- 任然时 a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

同样的，Lua 这边通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.g&lt;/code&gt; 获取到的字典变量的变化，也只有在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__newindex&lt;/code&gt; 函数被执行时，才会同步到 VimL 的变量。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wsd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;a&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;echo g:wsd&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;-- {&apos;a&apos; : &apos;a&apos;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wsd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;b&apos;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;echo g:wsd&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;-- 任然是 {&apos;a&apos; : &apos;a&apos;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sat, 01 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/from-vimscript-to-lua/</link>
        <guid isPermaLink="true">https://wsdjeg.net/from-vimscript-to-lua/</guid>
        
        <category>neovim</category>
        
        <category>lua</category>
        
        <category>VimScript</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>启用 Git Commit 签名</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#git-commit-签名&quot; id=&quot;markdown-toc-git-commit-签名&quot;&gt;Git Commit 签名&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#windows-安装-gpg&quot; id=&quot;markdown-toc-windows-安装-gpg&quot;&gt;Windows 安装 GPG&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#生成-gpg-密钥&quot; id=&quot;markdown-toc-生成-gpg-密钥&quot;&gt;生成 GPG 密钥&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#设置-git-签名程序&quot; id=&quot;markdown-toc-设置-git-签名程序&quot;&gt;设置 Git 签名程序&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

无意间阅读到一篇文章 &lt;a href=&quot;https://spencerwoo.com/blog/wait-this-is-not-my-commit/&quot;&gt;《震惊！竟然有人在 GitHub 上冒充我的身份！》&lt;/a&gt;, 大致看了下 Github 网站对于 Commit 的归属的判断规则。
只需要 Commit 的邮箱在某人的账号设置的邮箱列表内。那么就会将此次提交显示为是某人的归属。这就意味着，任何一个人都可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config user.email &quot;YOUR_EMAIL&quot;&lt;/code&gt; 这一命令设置成别人的邮箱，伪装成他人进行提交。

&lt;h2 id=&quot;git-commit-签名&quot;&gt;Git Commit 签名&lt;/h2&gt;

如果只需要设置邮箱就可以伪装成用户进行提交，那不是乱套了？因此大多数软件维护者都会要求 Commit 签名。Github 其实支持多种方式签名，这里大致记录一下自己设置 GPG 签名的方案。

&lt;h2 id=&quot;windows-安装-gpg&quot;&gt;Windows 安装 GPG&lt;/h2&gt;

Windows 系统下，我使用的 &lt;a href=&quot;https://scoop.sh/&quot;&gt;scoop&lt;/a&gt; 包管理器，通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scoop install gpg&lt;/code&gt; 就可以安装好了。 使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gpg --version&lt;/code&gt; 看一下版本信息。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;D:\wsdjeg&amp;gt;gpg --version
gpg (GnuPG) 2.4.7
libgcrypt 1.11.0
Copyright (C) 2024 g10 Code GmbH
License GNU GPL-3.0-or-later &amp;lt;https://gnu.org/licenses/gpl.html&amp;gt;
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: D:\Scoop\apps\gpg\current\home
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;生成-gpg-密钥&quot;&gt;生成 GPG 密钥&lt;/h2&gt;

参考 Github 的文档&lt;a href=&quot;https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key&quot;&gt;生成&lt;/a&gt;并&lt;a href=&quot;https://docs.github.com/en/authentication/managing-commit-signature-verification/adding-a-gpg-key-to-your-github-account&quot;&gt;上传&lt;/a&gt; GPG 密钥, 上传完成后使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https:/github.com/{username}.gpg&lt;/code&gt; 格式链接就可以访问你的公钥。

例如我的：&lt;a href=&quot;https://github.com/wsdjeg.gpg&quot;&gt;wsdjeg.gpg&lt;/a&gt;

&lt;h2 id=&quot;设置-git-签名程序&quot;&gt;设置 Git 签名程序&lt;/h2&gt;

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;where gpg&lt;/code&gt; 查看 gpg 命令的绝对路径：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;d:\wsdjeg&amp;gt;where gpg
D:\Scoop\apps\gpg\current\bin\gpg.exe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

清除之前的设置：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global --unset gpg.format
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

之前导入已备份的私钥后，使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit -S&lt;/code&gt; 一直提示没有私钥，找了很久原因才知道，原来需要设置 Git 的签名方式及程序，可能是原来设置过。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global gpg.program &quot;D:\Scoop\apps\gpg\current\bin\gpg.exe&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gpg --list-secret-keys --keyid-format=long&lt;/code&gt; 列出 GPG 密钥：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;d:\wsdjeg\my-blog&amp;gt;gpg --list-secret-keys --keyid-format=long
D:\Scoop\apps\gpg\current\home\pubring.kbx
------------------------------------------
sec   rsa2048/41BB7053E835C848 2021-09-21 [SC]
      9C957B574786F570AC69625041BB7053E835C848
uid                 [ unknown] Shidong Wang (Shidong&apos;s GPG key) &amp;lt;wsdjeg@outlook.com&amp;gt;
ssb   rsa2048/D3E3902EF4E8074C 2021-09-21 [E]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

设置 Git 签名的 ID：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global user.signingkey 41BB7053E835C848
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

设置 Git 默认启用 Commit 签名：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global commit.gpgsign true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 24 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/enable-git-commit-signing/</link>
        <guid isPermaLink="true">https://wsdjeg.net/enable-git-commit-signing/</guid>
        
        <category>git</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>从零开始制作实时搜索插件</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#窗口界面&quot; id=&quot;markdown-toc-窗口界面&quot;&gt;窗口界面&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#输入响应&quot; id=&quot;markdown-toc-输入响应&quot;&gt;输入响应&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#按键映射&quot; id=&quot;markdown-toc-按键映射&quot;&gt;按键映射&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#窗口内颜色高亮&quot; id=&quot;markdown-toc-窗口内颜色高亮&quot;&gt;窗口内颜色高亮&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#输入框美化&quot; id=&quot;markdown-toc-输入框美化&quot;&gt;输入框美化&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

当初，Neovim 刚刚推出异步 job 特性的时候，我就使用 Vim Script 写过一个实时检索的插件 &lt;a href=&quot;https://github.com/wsdjeg/FlyGrep.vim&quot;&gt;FlyGrep.vim&lt;/a&gt;。
最开始的实现是使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:split&lt;/code&gt; 命令分屏展示搜索结果，使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:echo&lt;/code&gt; 命令配合 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;while true getchar()&lt;/code&gt; 在 cmdline 内模拟输入框。

但是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:split&lt;/code&gt; 命令分屏时，总是带动整个界面其他窗口内容的移动。随着 Neovim 增加悬浮窗口这一特性，
我把 Flygrep 搜索结果窗口及底部提示状态都使用浮窗来实现，这就不会受到原先窗口界面布局的影响了。但是目前 Flygrep 的浮窗还是底部半屏窗口。

现在大多数浮窗插件都是在屏幕中间打开窗口，下面就从零开始一步一步实现一个简单的实时代码检索插件。

最终效果图如下：

&lt;img src=&quot;../images/float_grep_window.png&quot; alt=&quot;float grep window&quot; /&gt;

&lt;h2 id=&quot;窗口界面&quot;&gt;窗口界面&lt;/h2&gt;

首先时窗口界面，整体界面占据窗口中间 80% 区域，分上下两部分，下面窗口仅有一行，作为一个输入窗口，上面窗口作为搜索结果展示窗口。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 窗口位置&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 宽度： columns 的 80%&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;screen_width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;math.floor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;columns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 起始位位置： lines * 10%, columns * 10%&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;math.floor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;columns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;math.floor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 整体高度：lines 的 80%&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;screen_height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;math.floor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompt_bufid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompt_winid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_open_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prompt_bufid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;relative&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;editor&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;screen_width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;screen_height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;focusable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;border&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;rounded&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Input&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;title_pos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;center&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;-- noautocmd = true,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_bufid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_winid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_open_win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_bufid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;relative&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;editor&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;screen_width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;screen_height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;focusable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;border&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;rounded&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Result&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;title_pos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;center&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;-- noautocmd = true,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;输入响应&quot;&gt;输入响应&lt;/h2&gt;

在底部窗口输入内容时，后台自动执行搜索命令，并在搜索结果窗口实时展示。这里需要监控 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TextChangeI&lt;/code&gt; 这一事件，在事件 callback 函数内调用搜索命令。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;spacevim.api.job&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;augroup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;floatgrep&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;TextChangedI&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompt_bufid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_get_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prompt_bufid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;grep_cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;rg&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;--no-heading&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;--color=never&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;--with-filename&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;--line-number&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;--column&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-g&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;!.git&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-e&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;.&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;grep_cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;on_stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getbufline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_bufid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_set_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_bufid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_set_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_bufid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_set_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_bufid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上述代码中，我使用了 &lt;a href=&quot;https://spacevim.org&quot;&gt;spacevim&lt;/a&gt; job API，其实，我也考虑过使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.system()&lt;/code&gt; 函数，但是异步搜索完全不调用，
可能是写法有误, 使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.system()&lt;/code&gt; 写法如下（无效）：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;TextChangedI&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompt_bufid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_get_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prompt_bufid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;grep_cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;rg&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;--no-heading&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;--color=never&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;--with-filename&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;--line-number&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;--column&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-g&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;!.git&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;-e&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&apos;.&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;grep_cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_set_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_bufid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;按键映射&quot;&gt;按键映射&lt;/h2&gt;

因为输入框只有一行，因此避免回车键换行，同时增加在搜索结果窗口内上下移动两个快捷键。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 使用 Esc 关闭整个界面&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;i&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;Esc&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;noautocmd stopinsert&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prompt_winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompt_bufid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 搜索结果行转换成文件名、光标位置&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_file_pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fnameescape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[[:\d\+:]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linenr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str2nr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matchstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[[:\d\+:]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str2nr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;string.sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matchstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[[\(:\d\+\)\@&amp;lt;=:\d\+:]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linenr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colum&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 使用回车键打开光标所在的搜索结果，同时关闭界面&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;i&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;Enter&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;noautocmd stopinsert&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;-- 获取搜索结果光表行&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_get_cursor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linenr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_file_pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_get_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;result_bufid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;line_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;line_number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prompt_winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;edit &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_set_cursor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linenr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompt_bufid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 使用 Tab/Shift-Tab 上下移动搜素结果&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;i&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;Tab&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_get_cursor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_set_cursor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompt_bufid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;i&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;S-Tab&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_get_cursor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_win_set_cursor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_winid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompt_bufid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;窗口内颜色高亮&quot;&gt;窗口内颜色高亮&lt;/h2&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 高亮文件名及位置&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matchadd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&apos;Comment&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;[[\([A-Z]:\)\?[^:]*:\d\+:\(\d\+:\)\?]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_winid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;输入框美化&quot;&gt;输入框美化&lt;/h2&gt;

可以使用 extmarks 美化输入框，添加一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; 符号，禁用行号。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_set_option_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;number&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompt_winid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_set_option_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;relativenumber&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompt_winid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;floatgrep_ext&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_set_extmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prompt_bufid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sign_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sign_hl_group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Error&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码仅供参考，实际上还有很多细节并未完全考虑到，
比如 callback 函数内对于未执行完成的 job 的处理、
比如增加输入与搜索之间的延迟减少快速输入过程中不必要的额外执行搜索命令。

完整的代码可以看：&lt;a href=&quot;https://github.com/wsdjeg/.SpaceVim.d/tree/master/extra/simple_float_grep.lua&quot;&gt;simple_float_grep&lt;/a&gt;
</description>
        <pubDate>Thu, 23 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/create-a-searching-plugin-from-scratch/</link>
        <guid isPermaLink="true">https://wsdjeg.net/create-a-searching-plugin-from-scratch/</guid>
        
        <category>neovim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Neovim extmarks 功能介绍</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#什么是-extmark&quot; id=&quot;markdown-toc-什么是-extmark&quot;&gt;什么是 extmark&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#相关函数&quot; id=&quot;markdown-toc-相关函数&quot;&gt;相关函数&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#nvim_buf_set_extmark&quot; id=&quot;markdown-toc-nvim_buf_set_extmark&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_buf_set_extmark&lt;/code&gt;&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#id&quot; id=&quot;markdown-toc-id&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#end_row-和-end_col&quot; id=&quot;markdown-toc-end_row-和-end_col&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;end_row&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;end_col&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#hi_group&quot; id=&quot;markdown-toc-hi_group&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hi_group&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#hl_eol&quot; id=&quot;markdown-toc-hl_eol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hl_eol&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#virt_text&quot; id=&quot;markdown-toc-virt_text&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_text&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#virt_text_pos&quot; id=&quot;markdown-toc-virt_text_pos&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_text_pos&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#virt_text_win_col&quot; id=&quot;markdown-toc-virt_text_win_col&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_text_win_col&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#virt_text_hide&quot; id=&quot;markdown-toc-virt_text_hide&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_text_hide&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#hl_mode&quot; id=&quot;markdown-toc-hl_mode&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hl_mode&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#virt_lins&quot; id=&quot;markdown-toc-virt_lins&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_lins&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#virt_lines_above&quot; id=&quot;markdown-toc-virt_lines_above&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_lines_above&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#virt_lines_leftcol&quot; id=&quot;markdown-toc-virt_lines_leftcol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_lines_leftcol&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#right_gravity-和-end_right_gravity&quot; id=&quot;markdown-toc-right_gravity-和-end_right_gravity&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;right_gravity&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;end_right_gravity&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

Neovim 一直在迭代更新，本文以 Neovim v0.10.0 版本为基础进行功能演示。

&lt;h2 id=&quot;什么是-extmark&quot;&gt;什么是 extmark&lt;/h2&gt;

按照 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h extmark&lt;/code&gt; 描述 Extended marks (extmarks) 是跟踪缓冲区文本变化的的特定位置的注释。位置从 0 开始，位于第一个字符的前方。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     f o o b a r      line contents
     0 1 2 3 4 5      character positions (0-based)
    0 1 2 3 4 5 6     extmark positions (0-based)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;相关函数&quot;&gt;相关函数&lt;/h2&gt;

与 Neovim Extended marks 相关的函数有两个：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_buf_get_extmark&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_buf_set_extmark&lt;/code&gt;。

&lt;h3 id=&quot;nvim_buf_set_extmark&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_buf_set_extmark&lt;/code&gt;&lt;/h3&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_buf_set_extmark&lt;/code&gt; 的函数签名是：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nvim_buf_set_extmarks({buffer}, {ns_id}, {start}, {col}, {opts})
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

可以看到函数调用的参数包括 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ns_id&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;start&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;col&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opts&lt;/code&gt;。

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer&lt;/code&gt; 指的是设置 extmarks 对应的缓冲区 ID，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ns_id&lt;/code&gt; 全称是 name space id, 可以由 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_create_namespace&lt;/code&gt; 新建。

其中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opts&lt;/code&gt; 是一个 Lua table，比如：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_set_extmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;test_extmark&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end_row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end_col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hl_group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;TODO&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opts&lt;/code&gt; 支持的 Key 值及其含义包括：

&lt;h4 id=&quot;id&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;&lt;/h4&gt;

如果是新建一个 extmark 可以缺省，如果是修改某个已存在的 extmark，需要指定 id.

&lt;h4 id=&quot;end_row-和-end_col&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;end_row&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;end_col&lt;/code&gt;&lt;/h4&gt;

指定 extmark 结束的行和列，这里的列指的是行首、行尾或者字符之间，都是从 0 开始。

&lt;h4 id=&quot;hi_group&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hi_group&lt;/code&gt;&lt;/h4&gt;

&lt;h4 id=&quot;hl_eol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hl_eol&lt;/code&gt;&lt;/h4&gt;

这是一个布尔值，控制 extmark 覆盖的行尾无字符区域是否需要高亮。

&lt;h4 id=&quot;virt_text&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_text&lt;/code&gt;&lt;/h4&gt;

这是一个列表，其中每一个元素结构是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[text, highlight]&lt;/code&gt;。默认是添加在 extmark 开始的行行尾。

示例代码：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_set_extmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_namespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test_extmark&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;47&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;end_row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;47&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;end_col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;hl_group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;TODO&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;virt_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;This is &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Comment&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Number&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; extmarks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;TODO&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;virt_text_pos&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_text_pos&lt;/code&gt;&lt;/h4&gt;

设置虚拟文本的位置，可以设定的值为：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eol&lt;/code&gt;：行尾最后一个字符右边&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;overlay&lt;/code&gt;: 在 extmark 起始位置显示虚拟文本，覆盖的字符不右移&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;right_align&lt;/code&gt;: 在窗口最右侧显示&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inline&lt;/code&gt;: 在 extmark 起始位置显示虚拟文本，覆盖的字符右移&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;virt_text_win_col&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_text_win_col&lt;/code&gt;&lt;/h4&gt;

将 virtual text 展示在 fixed screen line，屏幕中可见的第一行为 0，往下依次加1。

&lt;h4 id=&quot;virt_text_hide&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_text_hide&lt;/code&gt;&lt;/h4&gt;

&lt;h4 id=&quot;hl_mode&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hl_mode&lt;/code&gt;&lt;/h4&gt;

设置高亮颜色的模式：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;replace&lt;/code&gt;: 默认，只显示 virtual text 颜色&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;combine&lt;/code&gt;: combine with background text color&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blend&lt;/code&gt;: blend with background text color&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;virt_lins&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_lins&lt;/code&gt;&lt;/h4&gt;

设置虚拟多行文本，每一行结构是多个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[text, highlight]&lt;/code&gt; 组成的列表。

&lt;h4 id=&quot;virt_lines_above&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_lines_above&lt;/code&gt;&lt;/h4&gt;

当设置虚拟多行文本时，默认是在 extmark 起始行下方，该选项设为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;，可以在上方显示。

&lt;h4 id=&quot;virt_lines_leftcol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt_lines_leftcol&lt;/code&gt;&lt;/h4&gt;

虚拟多行文本左对齐，绕过 sign 和 行号列

&lt;h4 id=&quot;right_gravity-和-end_right_gravity&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;right_gravity&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;end_right_gravity&lt;/code&gt;&lt;/h4&gt;

控制在 extmark 左右侧末端添加字符时 extmark 的位置扩展行为
</description>
        <pubDate>Sun, 19 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-extmarks/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-extmarks/</guid>
        
        <category>neovim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Neovim winbar 设置</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#什么是-winbar&quot; id=&quot;markdown-toc-什么是-winbar&quot;&gt;什么是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;winbar&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#使用-lua-设置-winbar&quot; id=&quot;markdown-toc-使用-lua-设置-winbar&quot;&gt;使用 lua 设置 winbar&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#redraw_winbar-函数实现&quot; id=&quot;markdown-toc-redraw_winbar-函数实现&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;redraw_winbar&lt;/code&gt; 函数实现&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#存在的一些问题&quot; id=&quot;markdown-toc-存在的一些问题&quot;&gt;存在的一些问题&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;什么是-winbar&quot;&gt;什么是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;winbar&lt;/code&gt;&lt;/h2&gt;

Neovim 0.8.0 就增加了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;winbar&apos;&lt;/code&gt; 这一选项。winbar 实际上类似于状态栏（statusline），只不过 winbar 是显示在每一个窗口的顶部。
它的设置格式与状态栏也完全一致。

这里做了一个简单的示例效果图：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot; 使用全局状态栏，状态栏只在底部显示，水平分割窗口将不再显示状态栏。&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;laststatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; 隐藏顶部标签栏&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;showtabline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;../images/winbar.png&quot; alt=&quot;winbar&quot; /&gt;

&lt;h2 id=&quot;使用-lua-设置-winbar&quot;&gt;使用 lua 设置 winbar&lt;/h2&gt;

前面也提到了 Neovim 实际上早就增加了 winbar，我是因为习惯了现有的状态栏和标签栏，不太像改变操作习惯。
最近正好想尝试使用一下 winbar 特性，因为之前写过自定义的标签栏、状态栏，因此配置起来还算顺手。

详细代码可以看我的 Github 仓库：&lt;a href=&quot;https://github.com/wsdjeg/winbar.nvim&quot;&gt;wsdjeg/winbar.nvim&lt;/a&gt;

实现的逻辑也比较简单，监控指定的 Neovim 事件，在 callback 函数内调用 redraw_winbar 函数。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;augroup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;winbar.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BufWinEnter&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;redraw_winbar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

我看过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fgheng/winbar.nvim&lt;/code&gt; 插件的代码，最后一次更新时间是 2022 年七月，在他的插件里 setup 函数直接这样写：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;winbar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;winbar.winbar&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;winbar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enabled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;DirChanged&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;CursorMoved&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BufWinEnter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BufFilePost&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;InsertEnter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BufWritePost&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;winbar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show_winbar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这会存在一个非常严重问题，就是如果使用者不小心调用了两次甚至多次 setup 函数，那么就会发现，实际上定义了多个重复的 autocmd。
因此不管是使用 Lua 来创建 autocmd 还是早期 Vim 下使用 Vim Script 创建 autocmd，都建议使用 augroup。

&lt;h2 id=&quot;redraw_winbar-函数实现&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;redraw_winbar&lt;/code&gt; 函数实现&lt;/h2&gt;

简单到极致的实现：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;redraw_winbar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;%:t&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%#SpaceVim_winbar#&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos; %#SpaceVim_winbar_Normal#&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default_conf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;winbar_seperator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%#Normal#&apos;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_set_option_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;winbar&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scope&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;local&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这里面其实有很多功能可以去做的，比如：

&lt;ol&gt;
  &lt;li&gt;排除 filetype&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;%:t&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ft&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filetype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;excluded_filetypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ft&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;文件名按正则表达式排除&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;excluded_regex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[[\.txt$]]&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;regex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;excluded_regex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;%:t&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;excluded_filetypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;存在的一些问题&quot;&gt;存在的一些问题&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;callback 函数内无法获取到触发这一事件的 windows ID，因为说白了，winbar 是一个 local to window 的选项，通过指定 winid 去修改其值才是最保险的。&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Tue, 14 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-winbar/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-winbar/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>自定义 quickfix 窗口格式</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#老旧方法&quot; id=&quot;markdown-toc-老旧方法&quot;&gt;老旧方法&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#使用-quickfixtextfunc&quot; id=&quot;markdown-toc-使用-quickfixtextfunc&quot;&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quickfixtextfunc&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

在 Neovim 或者 Vim 中，QuickFix 窗口内的内容默认的格式是：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;filename&amp;gt;|&amp;lt;lnum&amp;gt; col &amp;lt;col&amp;gt;|&amp;lt;text&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

最近有需求修改 QuickFix 窗口内容的格式，使其更加美观一些，修改前，QuickFix 窗口打开后内容如下：

&lt;img src=&quot;../images/quickfix-1.png&quot; alt=&quot;quickfix before&quot; /&gt;

而修改后最终展示的效果如下：

&lt;img src=&quot;../images/quickfix-2.png&quot; alt=&quot;quickfix before&quot; /&gt;

下面展示了两种修改方法，一个是在老旧的 Vim 内实现的方法，另外一个是借助 Vim 8.2 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qftf&lt;/code&gt; 选项实现的方式。

&lt;h2 id=&quot;老旧方法&quot;&gt;老旧方法&lt;/h2&gt;

早在 Vim 7.4 之前，可以使用 autocmd 来手动修改，其实现的逻辑是监控 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BufReadPost&lt;/code&gt; 事件

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; QuickFixFormat&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; qflist &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;getqflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;extend(v:val, {&quot;filename&quot; : bufname(v:val.bufnr)})&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; prefix_len &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;qflist&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;strchars(v:val.filename . v:val.lnum)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; fmt &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%-&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; prefix_len &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%s&apos;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;setlocal&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;modifiable&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;setline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;qflist&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;printf(fmt, v:val.filename . &quot;:&quot; . v:val.lnum, &quot;| &quot; . v:val.text)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;setlocal&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nomodifiable&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nomodified&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
augroup QuickFixFormat
  autocmd&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;
  autocmd &lt;span class=&quot;nb&quot;&gt;BufReadPost&lt;/span&gt; quickfix &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; QuickFixFormat&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
augroup END
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上述代码中，还可以把分隔符 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt; 修改成占据整行的竖线 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;│&lt;/code&gt;，以实现完整分割线效果。

完成窗口内容修改后，还存在一个问题，QuickFix 窗口里内容的高亮是通过 Vim 默认的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syntax/qf.vim&lt;/code&gt; 文件实现的，在这里需要覆盖默认的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qf&lt;/code&gt; FileType 的语法高亮：

Vim 可以新建 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.vim/syntax/qf.vim&lt;/code&gt; 文件，Neovim 是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/nvim/syntax/qf.vim&lt;/code&gt;。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;b:current_syntax&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;finish&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;syn&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;	qfFileName	&lt;span class=&quot;s2&quot;&gt;&quot;^[^│]*&quot;&lt;/span&gt; contains&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;qfLineNr
&lt;span class=&quot;k&quot;&gt;syn&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;	qfSeparator	&lt;span class=&quot;s2&quot;&gt;&quot;│&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;syn&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;	qfLineNr	&lt;span class=&quot;s2&quot;&gt;&quot;:\d*&quot;&lt;/span&gt; contained

&lt;span class=&quot;c&quot;&gt;&quot; The default highlighting.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;hi&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; link qfFileName	Directory
&lt;span class=&quot;k&quot;&gt;hi&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; link qfLineNr	LineNr
&lt;span class=&quot;k&quot;&gt;hi&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; link qfSeparator	VertSplit

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:current_syntax&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;qf&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;使用-quickfixtextfunc&quot;&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quickfixtextfunc&lt;/code&gt;&lt;/h2&gt;

上面的方法是强制修改 QuickFix Buffer 内容实现的格式化，Vim 8.2 提供了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quickfixtextfunc&lt;/code&gt; 选项，
可以通过设定这一选项来实现格式化 QuickFix 窗口，修改第一段代码为：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; QuickFixFormat&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;info&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; qflist &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getqflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;id&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;items&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;items&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; qflist &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;qflist&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;extend(v:val, {&quot;filename&quot; : bufname(v:val.bufnr)})&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; prefix_len &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;qflist&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;strchars(v:val.filename . v:val.lnum)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; fmt &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%-&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; prefix_len &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%s&apos;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;qflist&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;printf(fmt, v:val.filename . &quot;:&quot; . v:val.lnum, &quot;│ &quot; . v:val.text)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; quickfixtextfunc&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;QuickFixFormat
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if exists(&apos;&amp;amp;quickfixtextfunc&apos;)&lt;/code&gt; 来检测当前 Vim 或者 Neovim 是否支持 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quickfixtextfunc&lt;/code&gt; 选项。
</description>
        <pubDate>Fri, 10 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/custom-quickfix-format/</link>
        <guid isPermaLink="true">https://wsdjeg.net/custom-quickfix-format/</guid>
        
        <category>vim</category>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>《误杀3》观后感</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#关于剧情&quot; id=&quot;markdown-toc-关于剧情&quot;&gt;关于剧情&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#剧中人物&quot; id=&quot;markdown-toc-剧中人物&quot;&gt;剧中人物&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

结束了一天的工作，晚饭后去酒店旁边的电影院看了《误杀3》。

&lt;img src=&quot;../images/20250108.jpg&quot; alt=&quot;误杀3&quot; /&gt;

&lt;h2 id=&quot;关于剧情&quot;&gt;关于剧情&lt;/h2&gt;

看完重生，再来开这个确实觉得剧情太容易猜到剧情的发展了，看就没太大悬念了。不同于重生里面以毒品为话题，这部电影是以拐卖儿童这一敏感话题展开的，先不谈拍的好坏。起码让这个话题被更多的人关注到加以防范也算是起到一丁点的好处，让社会跟相关部门更多地关注到这个问题那就更好了。
回过头来再想想整部电影的剧情，感觉其中还是处处提供了线索，看的过程中还是能感觉出来一些人物的心理活动的。

&lt;h2 id=&quot;剧中人物&quot;&gt;剧中人物&lt;/h2&gt;

&lt;blockquote&gt;
  郑炳睿
&lt;/blockquote&gt;

一开始确实没想到他原来居然是人贩子，求生其实是生命的本能。人类虽然是高等动物，通过思想可以客服本能，但是还是会有人没办法克服，会依靠本能去做一些决定。
为了能活下去而参与贩卖人口等等，后来还是为了能活下去选择按下女儿那边炸弹的遥控器。虽然几个镜头也极力体现他对女儿的疼爱，比如看到女儿被伤害，哭的眼泪口水哒哒的。
关于这个角色心理的选择，我觉得有一个大的转变，从一开始怕死，而选择按下女儿那边炸弹遥控器，到后来奋不顾身地为女儿挡枪。

但是上面图片中的介绍真是扯淡, 郑炳睿出手爆杀人贩？？？他才是人贩子。图片剧情简介也完全是跟剧情实际情况截然相反。

&lt;blockquote&gt;
  李慧萍
&lt;/blockquote&gt;

电影开头第一眼，这女孩丢失八成跟她有关系，肯定是人贩子。后来证实下来确实是她参与的，但是没想到的是她原来也是是为了复仇。前后出镜截然两种不同风格人物，演员在演演员。

&lt;blockquote&gt;
  张景贤
&lt;/blockquote&gt;

误解了，一开始福利院收娃的长头发我以为是他。加上半夜出来杀郑炳睿，我还以为他是达蒙的人。后来看到原来他的妻子是梁素娥，才知道他也是要复仇的。

&lt;blockquote&gt;
  雅英
&lt;/blockquote&gt;

我脸盲，看了好几次才把她跟丢失娃的母亲对上号。

&lt;blockquote&gt;
  吴达毅
&lt;/blockquote&gt;

最后杀他的是谁？

&lt;blockquote&gt;
  施福安和Tinaya
&lt;/blockquote&gt;

没啥感触，死得其所。

&lt;blockquote&gt;
  阿卢
&lt;/blockquote&gt;

第一个镜头，就看到仇恨的眼光，审判室里的大笑也没看懂，直到知道他也是丢失儿童的家属，一切才显得那么理所当然。

&lt;blockquote&gt;
  达蒙
&lt;/blockquote&gt;

最后啥他的人是谁？

&lt;blockquote&gt;
  门多萨
&lt;/blockquote&gt;

一开始以为他是一无是处的领导。

&lt;blockquote&gt;
  梁素娥
&lt;/blockquote&gt;

最有感触的还是梁素娥的剧情，感觉词穷了，不知道该怎么写。第一次出镜的时候，感觉挺好看，一张混血儿脸，心善，“我也是孩子母亲，我一定会找到真相”，台词可能我记错了，但是我想她所想表达的意思以及她所坚持的事情一定是这样的，也为此付出了生命，也包括还没出生的孩子。

&lt;blockquote&gt;
  阿佐
&lt;/blockquote&gt;

开第一枪的男警察？

&lt;blockquote&gt;
  阿婕
&lt;/blockquote&gt;

不记得谁了，女警察？

&lt;blockquote&gt;
  郑婷婷
&lt;/blockquote&gt;

最后开枪的是谁？
</description>
        <pubDate>Wed, 08 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/20250108/</link>
        <guid isPermaLink="true">https://wsdjeg.net/20250108/</guid>
        
        <category>movie</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>Neovim quickfix 窗口内的一些快捷键</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#删除单行或者多行&quot; id=&quot;markdown-toc-删除单行或者多行&quot;&gt;删除单行或者多行&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#结果过滤filter&quot; id=&quot;markdown-toc-结果过滤filter&quot;&gt;结果过滤（Filter）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

Neovim 的 quickfix 窗口还是比较常用的功能，在这里，我实现了一些 quickfix 窗口内常用的快捷键。

&lt;h2 id=&quot;删除单行或者多行&quot;&gt;删除单行或者多行&lt;/h2&gt;

在 quickfix 窗口内，默认情况下 Normal 模式下的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dd&lt;/code&gt; 和 Visual 模式下的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt; 快捷键是不可用的，会提示:

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;E21: Cannot make changes, &apos;modifiable&apos; is off
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

但是有时候，会感觉 quickfix 展示的结果太多了，有些内容不是我所需要的。使用如下代码实现了 Normal 模式下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dd&lt;/code&gt; 删除光标下的结果，Visual 模式下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt; 删除选中行的结果。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;quickfix_mapping&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;FileType&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;qf&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;dd&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qflist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getqflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;.&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;table.remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setqflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tostring&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;table_remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rst&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;rst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rst&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;-- else&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;-- i = to + 1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rst&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;FileType&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;qf&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;v&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;d&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;esc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_replace_termcodes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;esc&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_feedkeys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;esc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;x&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qflist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getqflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getpos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&apos;&amp;lt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getpos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&apos;&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;qflist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table_remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setqflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tostring&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;结果过滤filter&quot;&gt;结果过滤（Filter）&lt;/h2&gt;

这里主要是为了实现一个功能，移除文件路径匹配输入表达式的结果。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;quickfix_mapping&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;FileType&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;qf&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;c&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input_pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;filter pattern:&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;-- vim.cmd(&apos;noautocmd normal! :&apos;)&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;regex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getqflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bufname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bufnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
          &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setqflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上述代码，设定的快捷键为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt;, 按下快捷键后会弹出一个出入提示，输入一段字符串，可以是 Vim 正则，回车后会移除 quickfix 窗口中文件名称匹配字符串的结果。

如果需要保留文件名匹配字符串的结果，可以增加一个新的快捷键，比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C&lt;/code&gt;，代码如下：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;quickfix_mapping&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;FileType&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;qf&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;C&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input_pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;filter pattern:&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;-- vim.cmd(&apos;noautocmd normal! :&apos;)&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;regex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getqflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bufname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bufnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
          &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setqflist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上述功能汇总为插件 &lt;a href=&quot;https://github.com/wsdjeg/quickfix.nvim&quot;&gt;quickfix.nvim&lt;/a&gt;.
</description>
        <pubDate>Mon, 30 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/key-bindings-for-neovim-quickfix-window/</link>
        <guid isPermaLink="true">https://wsdjeg.net/key-bindings-for-neovim-quickfix-window/</guid>
        
        <category>neovim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Vim/Neovim 中使用正则表达式</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#元字符&quot; id=&quot;markdown-toc-元字符&quot;&gt;元字符&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#替换变量&quot; id=&quot;markdown-toc-替换变量&quot;&gt;替换变量&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#函数式&quot; id=&quot;markdown-toc-函数式&quot;&gt;函数式&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#与-perl-正则表达式的区别&quot; id=&quot;markdown-toc-与-perl-正则表达式的区别&quot;&gt;与 Perl 正则表达式的区别&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#贪婪模式和非贪婪模式&quot; id=&quot;markdown-toc-贪婪模式和非贪婪模式&quot;&gt;贪婪模式和非贪婪模式&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#neovim-中使用正则表达式&quot; id=&quot;markdown-toc-neovim-中使用正则表达式&quot;&gt;Neovim 中使用正则表达式&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

2018 年 8 月 28 日，我在 CSDN 博客上面发表过一篇文章：&lt;a href=&quot;https://blog.csdn.net/wsdjeg/article/details/82145321&quot;&gt;《Vim 中使用正则表达式》&lt;/a&gt;。
随着 CSDN 账号的注销，这篇文章已经无法在更新，于是将文章迁移至个人博客，并加以更新，增加 Neovim 相关内容。

经常在网上看到有人抱怨 Vim 的正则表达式太奇怪，无法接受。我倒是觉得 Vim 的正则表达式比较容易理解。
可能是因为我最早接触的正则表达式就是 Vim 的正则表达式吧，正好借此机会整理下 Vim 的正则表达式相关的内容。

首先，在哪些情况下会用到正则表达式？

使用正则表达式的命令最常见的就是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt; 命令。其格式如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/正则表达式
?正则表达式
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

另一个很有用的命令就是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:s[ubstitute]&lt;/code&gt;（替换）命令，将第一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;//&lt;/code&gt;之间的正则表达式替换成第二个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;//&lt;/code&gt;之间的字符串。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:s/正则表达式/替换字符串/选项
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在学习正则表达式时可以利用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; 命令来练习。

&lt;h2 id=&quot;元字符&quot;&gt;元字符&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;元字符&lt;/th&gt;
      &lt;th&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配任意字符&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[abc]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配方括号中的任意一个字符。可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt; 表示字符范围，如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[a-z0-9]&lt;/code&gt;匹 配小写字母和阿拉伯数字。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配阿拉伯数字，等同于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[0-9]&lt;/code&gt;。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[^abc]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;在方括号内开头使用^符号，表示匹配除方括号中字符之外的任意字符。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配阿拉伯数字，等同于[0-9]。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\D&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配阿拉伯数字之外的任意字符，等同于[^0-9]。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\x&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配十六进制数字，等同于[0-9A-Fa-f]。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\X&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配十六进制数字之外的任意字符，等同于[^0-9A-Fa-f]。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\w&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配单词字母，等同于[0-9A-Za-z_]。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\W&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配单词字母之外的任意字符，等同于[^0-9A-Za-z_]。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\t&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配字符。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\s&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配空白字符，等同于[ \t]。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\S&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配非空白字符，等同于[^ \t]。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

如果需要查找一些特殊字符，如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; 等，可以在这些字符前面添加 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&lt;/code&gt;，表示这些不是元字符，而是普通字符。比如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\/d&lt;/code&gt; 匹配的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/d&lt;/code&gt;这两个字符，而不是匹配任意数字。

&lt;strong&gt;表示数量的元字符&lt;/strong&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;元字符&lt;/th&gt;
      &lt;th&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配0-任意个&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\+&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配1-任意个&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\?&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配0-1个&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\{n,m}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配n-m个&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\{n}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配n个&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\{n,}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配n-任意个&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\{,m}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配0-m个&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;strong&gt;表示位置的符号&lt;/strong&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;元字符&lt;/th&gt;
      &lt;th&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配行尾&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配行首&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&amp;lt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配单词词首&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;匹配单词词尾&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;strong&gt;使用示例&lt;/strong&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;命令&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/char\s\+[A-Za-z_]\w*;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;查找所有以char开头，之后是一个以上的空白，最后是一个标识符和分号&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/\d\d:\d\d:\d\d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;查找如 17:37:01 格式的时间字符&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:g/^\s*$/d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;删除只有空白的行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:s/\&amp;lt;four\&amp;gt;/4/g&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;将所有的 four 替换成 4，但是 fourteen 中的 four 不替换&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;替换变量&quot;&gt;替换变量&lt;/h2&gt;

在正规表达式中使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\(&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\)&lt;/code&gt; 符号括起正规表达式，即可在后面使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\1&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\2&lt;/code&gt; 等变量来访问 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\(&lt;/code&gt;和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\)&lt;/code&gt; 中的内容。

&lt;strong&gt;使用示例&lt;/strong&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;命令&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/\(a\+\)[^a]\+\1&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;查找开头和结尾处a的个数相同的字符串，如 aabbbaa，aaacccaaa，但是不匹配 abbbaa&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:s/\(http:\/\/[-a-z\._~\+%\/]\+\)/&amp;lt;a href=&quot;\1&quot;&amp;gt;\1&amp;lt;\/a&amp;gt;/&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;将 url 替换为&lt;a href=&quot;http://url&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://url&quot;&gt;http://url&lt;/a&gt;的格式&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:s/\(\w\+\)\s\+\(\w\+\)/\2\t\1&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;将 data1 data2 修改为 data2 data1&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;函数式&quot;&gt;函数式&lt;/h2&gt;

在替换命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:s/{pattern}/{string}/[flags]&lt;/code&gt; 中可以使用函数表达式来书写替换内容，格式为

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:s/替换字符串/\=函数式
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在函数式中可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;submatch(1)&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;submatch(2)&lt;/code&gt; 等来引用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\1&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\2&lt;/code&gt; 等的内容，而&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;submatch(0)&lt;/code&gt;可以引用匹配的整个内容。

&lt;strong&gt;使用例&lt;/strong&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:%s/\&amp;lt;id\&amp;gt;/\=line(&quot;.&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

将各行的 id 字符串替换为行号

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:%s/^\&amp;lt;\w\+\&amp;gt;/\=(line(&quot;.&quot;)-10) .&quot;.&quot;. submatch(1)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

将每行开头的单词替换为 (行号-10).单词 的格式，如第11行的 word 替换成 1. word

&lt;h2 id=&quot;与-perl-正则表达式的区别&quot;&gt;与 Perl 正则表达式的区别&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Vim语法&lt;/th&gt;
      &lt;th&gt;Perl语法&lt;/th&gt;
      &lt;th&gt;含义&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\+&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;1-任意个&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\?&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;0-1个&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\{n,m}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{n,m}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;n-m个&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\(&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;分组&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;贪婪模式和非贪婪模式&quot;&gt;贪婪模式和非贪婪模式&lt;/h2&gt;

在 Vim 里，默认是贪婪模式，即 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a.*b&lt;/code&gt; 会尽可能多滴匹配字符，在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ahdbjkbkls&lt;/code&gt; 中匹配 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ahdbjkb&lt;/code&gt; 而不是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ahdb&lt;/code&gt;。&lt;br /&gt;
如果是非贪婪的，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\{-}&lt;/code&gt; 代替 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;，即 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a.\{-}b&lt;/code&gt; 匹配 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ahdb&lt;/code&gt; 而不是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ahdbjkb&lt;/code&gt;。

&lt;h2 id=&quot;neovim-中使用正则表达式&quot;&gt;Neovim 中使用正则表达式&lt;/h2&gt;

Neovim 目前主要的配置语言是 Lua，并且 Lua 并没有 VimL 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=~#&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=~&lt;/code&gt; 比较符。但是 Neovim 提供了一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.regex&lt;/code&gt; Lua 模块。

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.regex&lt;/code&gt; 模块常见的使用方式：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;regex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;http[s]*://&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- do something&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;abc12332324def&apos;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;regex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;+&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 29 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/using-regular-expressions-in-vim-and-neovim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/using-regular-expressions-in-vim-and-neovim/</guid>
        
        <category>vim</category>
        
        <category>neovim</category>
        
        <category>regexp</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 状态栏及标签栏点击事件</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#什么是-tablineat&quot; id=&quot;markdown-toc-什么是-tablineat&quot;&gt;什么是 tablineat&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#测试标签栏点击事件&quot; id=&quot;markdown-toc-测试标签栏点击事件&quot;&gt;测试标签栏点击事件&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#多次点击存在的问题&quot; id=&quot;markdown-toc-多次点击存在的问题&quot;&gt;多次点击存在的问题&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;什么是-tablineat&quot;&gt;什么是 tablineat&lt;/h2&gt;

熟悉 Vim 或者 Neovim 的用户对于其状态栏（statusline）和标签栏（tabline）应该也不陌生，对于这两个 UI 组件上面的点击事件，
早期是只有 tabline 上面支持点击操控 Vim 的标签页。

很早以前，就有用户想在 vim-airline 插件的标签栏实现 &lt;a href=&quot;https://github.com/vim-airline/vim-airline/issues/369&quot;&gt;Buffer 切换的功能&lt;/a&gt;，
但是似乎直到现在，Vim 都未增加该功能。

2016 年，Neovim &lt;a href=&quot;https://github.com/neovim/neovim/pull/3871&quot;&gt;增加了 tablineat 特性&lt;/a&gt;，使得用户可以在自定义状态栏和标签栏时，
指定某个区域设定对应的点击事件回调函数，以此实现监控状态栏和标签栏的点击事件。可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;has(&apos;tablineat&apos;)&lt;/code&gt; 检测当前 Neovim 是否支持该特性。

以下内容摘自 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h statusline&lt;/code&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@ N   Start of execute function label. Use %X or %T to end the label,
      e.g.: %10@SwitchBuffer@foo.c%X.  Clicking this label runs the
      specified function: in the example when clicking once using left
      mouse button on &quot;foo.c&quot;, a `SwitchBuffer(10, 1, &apos;l&apos;, &apos;    &apos;)`
      expression will be run.  The specified function receives the
      following arguments in order:
      1. minwid field value or zero if no N was specified
      2. number of mouse clicks to detect multiple clicks
      3. mouse button used: &quot;l&quot;, &quot;r&quot; or &quot;m&quot; for left, right or middle
         button respectively; one should not rely on third argument
         being only &quot;l&quot;, &quot;r&quot; or &quot;m&quot;: any other non-empty string value
         that contains only ASCII lower case letters may be expected
         for other mouse buttons
      4. modifiers pressed: string which contains &quot;s&quot; if shift
         modifier was pressed, &quot;c&quot; for control, &quot;a&quot; for alt and &quot;m&quot;
         for meta; currently if modifier is not pressed string
         contains space instead, but one should not rely on presence
         of spaces or specific order of modifiers: use |stridx()| to
         test whether some modifier is present; string is guaranteed
         to contain only ASCII letters and spaces, one letter per
         modifier; &quot;?&quot; modifier may also be present, but its presence
         is a bug that denotes that new mouse button recognition was
         added without modifying code that reacts on mouse clicks on
         this label.
      Use |getmousepos()|.winid in the specified function to get the
      corresponding window id of the clicked item.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;测试标签栏点击事件&quot;&gt;测试标签栏点击事件&lt;/h2&gt;

按照前面的帮助文档描述的内容，可以使用格式 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%N@function_name@text%X&lt;/code&gt; 来指定区域监控点击事件，
回调函数的名称为两个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; 标记之间的字符串，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; 之间的数字作为第一个参数。

写一个测试函数，看一看点击事件的具体执行效果：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; OnClick&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; abort
  &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:a&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:b&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:c&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;gt;&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;&apos;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tabline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;xxxxxxx%&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;@OnClick@&lt;span class=&quot;m&quot;&gt;11111&lt;/span&gt;%X%&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;@OnClick@&lt;span class=&quot;m&quot;&gt;22222&lt;/span&gt;%X
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

将以上文件保存为 vim 文件并执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:so %&lt;/code&gt; 后，状态栏变成了
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xxxxxxx1111122222&lt;/code&gt;, 鼠标左键单击 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;11111&lt;/code&gt; 区域，看到如下输出。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1
1
l
&amp;gt;    &amp;lt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上述四行分别对应函数的四个参数:

&lt;ul&gt;
  &lt;li&gt;第一个参数是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; 之间的数字&lt;/li&gt;
  &lt;li&gt;第二个参数是鼠标点击的次数&lt;/li&gt;
  &lt;li&gt;第三个参数是鼠标键位, 可以是左键（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;l&lt;/code&gt;）、右键（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt;）或者中键（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m&lt;/code&gt;）&lt;/li&gt;
  &lt;li&gt;第四个参数对应的时按下的组合键，Ctrl 键（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt;）、Shift 键（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt;）、Alt 键（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt;）、Meta 键（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m&lt;/code&gt;）&lt;/li&gt;
  &lt;li&gt;最后一个参数是对应的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shift/alt/ctrl&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;多次点击存在的问题&quot;&gt;多次点击存在的问题&lt;/h2&gt;

在使用前面的测试脚本测试的过程中，发现第二个参数返回的是点击的次数，其结果不是完全可预期的。为了更加方便测试，将测试的脚本修改如下：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; OnClick&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; abort
  &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;点击次数：&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:b&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tabline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;xxxxxxx%&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;@OnClick@&lt;span class=&quot;m&quot;&gt;11111&lt;/span&gt;%X%&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;@OnClick@&lt;span class=&quot;m&quot;&gt;22222&lt;/span&gt;%X
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

多次点击后，其结果如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;点击次数：1
点击次数：2
点击次数：3
点击次数：4
点击次数：1
点击次数：2
点击次数：3
点击次数：4
点击次数：1
点击次数：2
点击次数：1
点击次数：2
点击次数：3
点击次数：4
点击次数：1
点击次数：2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上面的输出可以看到，当连续点击时，回调函数会在每次点击时被调用。并且点击次数会增加，
当间隔时间超过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mousetime&lt;/code&gt; 时，点击次数计数归零，
间隔时间可以查阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h mousetime&lt;/code&gt;, 默认为 500 毫秒。
</description>
        <pubDate>Sat, 28 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-tabline-statusline-click-events/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-tabline-statusline-click-events/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>代码格式化插件 format.nvim</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#前因&quot; id=&quot;markdown-toc-前因&quot;&gt;前因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#插件的安装&quot; id=&quot;markdown-toc-插件的安装&quot;&gt;插件的安装&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#自定义-formatter&quot; id=&quot;markdown-toc-自定义-formatter&quot;&gt;自定义 formatter&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#插件的使用&quot; id=&quot;markdown-toc-插件的使用&quot;&gt;插件的使用&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#markdown-代码块格式化&quot; id=&quot;markdown-toc-markdown-代码块格式化&quot;&gt;Markdown 代码块格式化&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;前因&quot;&gt;前因&lt;/h2&gt;

最近，我在 &lt;a href=&quot;https://www.reddit.com/r/neovim/comments/1hhu10r/formatnvim_asynchronous_code_formatting_plugin/&quot;&gt;Reddit&lt;/a&gt;
上面分享了一个新的代码格式化的插件 &lt;a href=&quot;https://github.com/wsdjeg/format.nvim&quot;&gt;format.nvim&lt;/a&gt;，
回复大多是是在问为什么要做这个插件以及跟现有插件的区别。

在 SpaceVim v2.3.0 之前，一直使用的代码格式化插件是 &lt;a href=&quot;https://github.com/sbdchd/neoformat&quot;&gt;neoformat&lt;/a&gt;, 这个插件是使用 Vim 脚本写的，同时支持 Neovim 和 Vim。
但是美中不足的地方是这个插件执行格式化命令是调用 Vim 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system()&lt;/code&gt; 函数，当命令执行消耗时间很长时，就会卡住界面无法进行下一步操作。
我也尝试过给 neoformat 增加异步支持，但是最终还是决定重新开发一个插件，
主要市考虑到以下几个原因：

&lt;ul&gt;
  &lt;li&gt;Lua 尤其是 luajit 速度相较于 Vim 脚本要快很多，相关比较文章可以查看我前面写的&lt;a href=&quot;https://wsdjeg.net/rewrite-spacevim-builtin-plugin-using-lua/&quot;&gt;使用 Lua 重写 SpaceVim 内置插件&lt;/a&gt;和&lt;a href=&quot;https://wsdjeg.net/speed-comparison-between-vim9script-and-lua/&quot;&gt;Vim9Script 与 Lua 的速度比较&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;做一个格式化插件的框架，尽可能减少默认的 formatter，提供接口自行定义。&lt;/li&gt;
  &lt;li&gt;不需要太过复杂的功能，仅仅是异步执行指定命令并更新 Neovim 缓冲区。&lt;/li&gt;
&lt;/ul&gt;

其实 neoformat 的插件代码实现逻辑还是非常好的，因此我也是参考了 neoformat 的实现逻辑，
使用 Lua 来实现了这个异步代码格式化的插件 &lt;a href=&quot;https://github.com/wsdjeg/format.nvim&quot;&gt;format.nvim&lt;/a&gt;。
这个插件使用了 &lt;a href=&quot;https://spacevim.org/cn/api/job/&quot;&gt;SpaceVim 的 job api&lt;/a&gt; 可以异步执行格式化命令，使得 Neovim 的操作更加顺畅。

&lt;h2 id=&quot;插件的安装&quot;&gt;插件的安装&lt;/h2&gt;

可以使用任意插件管理器，比如&lt;a href=&quot;https://github.com/wsdjeg-nvim-plug&quot;&gt;nvim-plug&lt;/a&gt;来进行安装：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/format.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cmds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Format&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;depends&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/job.nvim&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/notify.nvim&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

对于 SpaceVim 用户来说，只需要在启用 format 模块的时候，指定格式化方法为 format.nvim 即可，配置如下：

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;format&apos;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;format_method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;format.nvim&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;自定义-formatter&quot;&gt;自定义 formatter&lt;/h2&gt;

以 Lua 语言为例，设置使用 stylua 命令进行格式化：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;format&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;custom_formatters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;lua&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;exe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;stylua&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;stdin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;插件的使用&quot;&gt;插件的使用&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;格式化整个文件&lt;/li&gt;
&lt;/ol&gt;

format.nvim 只提供了一个命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Fromat&lt;/code&gt;, 执行该命令时就可以根据当前文件的文件类型选择对应的 formatter 对整个 Buffer 进行格式化。

&lt;ol&gt;
  &lt;li&gt;选中区域进行格式化&lt;/li&gt;
&lt;/ol&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Format&lt;/code&gt; 命令支持指定区域进行格式化，因此可以在 Neovim 中选中几行代码进行格式化。

&lt;ol&gt;
  &lt;li&gt;指定文件类型&lt;/li&gt;
&lt;/ol&gt;

通常执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Format&lt;/code&gt; 命令时，会读取当前 Buffer 的 &amp;amp;filetype 选项，但是如果需要指定其他文件类型，比如 java，可以使用如下格式执行命令：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:Format! &amp;lt;filetype&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;指定格式化工具&lt;/li&gt;
&lt;/ol&gt;

如果一个文件类型有多个 formatters，可以在执行改命令时指定一个 formatter 的名字，比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Format prettier&lt;/code&gt;

&lt;ol&gt;
  &lt;li&gt;同时指定文件类型、格式化工具，比如选中 markdown 内一段代码块进行格式化：&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:Format! &amp;lt;filetype&amp;gt; &amp;lt;formatter&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;markdown-代码块格式化&quot;&gt;Markdown 代码块格式化&lt;/h2&gt;

前面提到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Format&lt;/code&gt; 命令支持指定区域格式，这里需要借助一个插件 &lt;a href=&quot;https://github.com/Shougo/context_filetype.vim&quot;&gt;context_filetype.vim&lt;/a&gt;。
通过这个插件获取到代码块的区域和文件类型，传给 Format 命令。

以下示例使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Leader&amp;gt;f&lt;/code&gt; 格式化光标所在的代码块：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:format_code_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; abort
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;cf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; context_filetype#&lt;span class=&quot;nb&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;filetype&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;markdown&apos;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; command &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;%s,%sFormat! %s&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;filetype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    exe command
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;silent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;Leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;cmd&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;sid&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;format_code_block&lt;span class=&quot;p&quot;&gt;()&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Wed, 25 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/code-formatting-plugin-format-nvim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/code-formatting-plugin-format-nvim/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>在 SpaceVim 中使用卢曼卡片盒笔记法做笔记</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#基于-neovim-的-zettelkasten-插件&quot; id=&quot;markdown-toc-基于-neovim-的-zettelkasten-插件&quot;&gt;基于 Neovim 的 zettelkasten 插件&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#基于-tags-的-zkbrowser&quot; id=&quot;markdown-toc-基于-tags-的-zkbrowser&quot;&gt;基于 Tags 的 ZkBrowser&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#使用-telescope-检索-tags&quot; id=&quot;markdown-toc-使用-telescope-检索-tags&quot;&gt;使用 Telescope 检索 Tags&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#使用-telescope-检索标题&quot; id=&quot;markdown-toc-使用-telescope-检索标题&quot;&gt;使用 Telescope 检索标题&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#补全笔记-id&quot; id=&quot;markdown-toc-补全笔记-id&quot;&gt;补全笔记 ID&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#笔记模板的筛选&quot; id=&quot;markdown-toc-笔记模板的筛选&quot;&gt;笔记模板的筛选&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#vim-的支持&quot; id=&quot;markdown-toc-vim-的支持&quot;&gt;Vim 的支持&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#参考文章&quot; id=&quot;markdown-toc-参考文章&quot;&gt;参考文章：&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

前段时间整理自己的个人维基发现笔记太零散，很难快速定位到自己需要的笔记。
以往借助自己的 &lt;a href=&quot;https://github.com/wsdjeg/FlyGrep.vim&quot;&gt;flygrep&lt;/a&gt; 插件根据记忆的关键字倒是可以找到相关的内容，
但是随着笔记越来越多，关键字筛选已经不足以快速定位了。
于是就想找一个更好的方式来组织管理日常的笔记，后来就了解到了《&lt;a href=&quot;https://zettelkasten.de/introduction/zh/&quot;&gt;卢曼卡片盒笔记法&lt;/a&gt;》

&lt;h2 id=&quot;基于-neovim-的-zettelkasten-插件&quot;&gt;基于 Neovim 的 zettelkasten 插件&lt;/h2&gt;

最开始，我是想找一个三端（手机、电脑、网页）同步的笔记软件，但是似乎没有合适的。因为都是文本编辑，而且如果要使用卡片盒笔记法的话，
那么笔记就需要遵循一定的格式。日常使用 Neovim 也非常多，几乎文本的编辑都是在 Neovim 内完成的，索性就不再舍近求远去找笔记软件了，
就直接在 Neovim 内完成。检索了下 Github 发现还是有不少现成的插件实现，但是功能似乎都不是很完善。

因此自己 Fork 了一个插件，在这个插件的基础上做了一些功能的改进和增加，有兴趣的话欢迎尝试：&lt;a href=&quot;https://github.com/wsdjeg/vim-zettelkasten&quot;&gt;vim-zettelkasten&lt;/a&gt;。

&lt;h3 id=&quot;基于-tags-的-zkbrowser&quot;&gt;基于 Tags 的 ZkBrowser&lt;/h3&gt;

浏览笔记列表时，展示笔记的引用数量以及被引用数量，同时列出笔记包含的 Tags 列表，如下图所示：

&lt;img src=&quot;../images/zkbrowser.png&quot; alt=&quot;&quot; /&gt;

同时，在 ZkBrowser 窗口内支持的快捷键包括：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;快捷键&lt;/th&gt;
      &lt;th&gt;功能描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;q&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;退出 ZkBrowser 窗口&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;LeftRelease&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;鼠标左键点击 Tag，筛选包含该 Tag 的笔记&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gf&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;打开光标 ID 下的笔记&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-l&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;清除 Tags 筛选，列出所有笔记&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;使用 preview-window 窗口预览笔记&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[I&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;使用 quickfix-window 列出 References&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F2&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;打开 Tags 列表侧栏&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

侧栏的效果图如下，可以在侧栏窗口中使用回车键或者鼠标左键点击 Tag 实现筛选：

&lt;img src=&quot;../images/zettelkasten-tags-sidebar.png&quot; alt=&quot;&quot; /&gt;

侧栏中，标签按照首字母归类，鼠标左键点击归类的字母，可以折叠这些标签。

&lt;h3 id=&quot;使用-telescope-检索-tags&quot;&gt;使用 Telescope 检索 Tags&lt;/h3&gt;

当笔记 Tags 非常多的时候，可以使用 telescope.nvim 进行检索，检索后默认的回车键行为是列出包含该 Tag 的所有笔记。
默认的快捷键为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPC m z g&lt;/code&gt;。

&lt;img src=&quot;../images/zettelkasten-tags-filter.png&quot; alt=&quot;&quot; /&gt;

&lt;h3 id=&quot;使用-telescope-检索标题&quot;&gt;使用 Telescope 检索标题&lt;/h3&gt;

笔记的标题（Title）也可以使用 telescope.nvim 进行检索，默认的快捷键是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPC m z f&lt;/code&gt;。

&lt;img src=&quot;../images/zettelkasten-title.png&quot; alt=&quot;&quot; /&gt;

&lt;h3 id=&quot;补全笔记-id&quot;&gt;补全笔记 ID&lt;/h3&gt;

在编辑笔记过程中，可以使用快捷键 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctrl-x ctrl-u&lt;/code&gt; 来打开补全窗口，补全引用的笔记 ID。

&lt;img src=&quot;../images/zettelkasten-complete-id.png&quot; alt=&quot;&quot; /&gt;

&lt;h3 id=&quot;笔记模板的筛选&quot;&gt;笔记模板的筛选&lt;/h3&gt;

如果是使用 SpaceVim，可以通过 zettelkasten 模块选项设置笔记模板的文件夹，新建一些常用的笔记模板，比如：

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;zettelkasten&apos;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zettel_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;D:\me\zettelkasten&apos;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zettel_template_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;D:\me\zettelkasten_template&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

通常基于默认新建笔记直接使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPC m z n&lt;/code&gt; 快捷键即可，如果需要基于其他模板来新建，可以使用快捷键 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPC m z t&lt;/code&gt; 调用 Telescope 检索常用模板。

&lt;h2 id=&quot;vim-的支持&quot;&gt;Vim 的支持&lt;/h2&gt;

因为 SpaceVim 默认是兼容 Neovim 和 Vim 的，因此后面是有计划让这个插件也支持 Vim 的，但是为了减少重复实现的一些代码，可能是需要 Vim 有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+lua&lt;/code&gt; 特性。

&lt;h2 id=&quot;参考文章&quot;&gt;参考文章：&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://skywind.me/blog/archives/2667&quot;&gt;什么是 Zettelkasten 卡片盒笔记法？&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mp.weixin.qq.com/s?__biz=MzA5MzUzODA1OA==&amp;amp;mid=2247483947&amp;amp;idx=1&amp;amp;sn=2cccb76ee58ddd11541d91c4b283b594&amp;amp;chksm=905d104ea72a9958d71c70313d5a4799641aa903e62f32ac1038ec5fb8c903fc7db36c261d26&amp;amp;cur_album_id=1477367917246726144&amp;amp;scene=189#wechat_redirect&quot;&gt;卢曼：与卡片盒交流&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mp.weixin.qq.com/s?__biz=MzA5MzUzODA1OA==&amp;amp;mid=2247483824&amp;amp;idx=1&amp;amp;sn=1414f5af0d635b5900a0888c11cff1e9&amp;amp;chksm=905d13d5a72a9ac3397472a482db71ecd16820d3c506a1e9d2adaa6ef30eb28589ed2f257321&amp;amp;scene=21#wechat_redirect&quot;&gt;卢曼：学习如何阅读&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 11 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/zettelkasten-method-plugin-for-spacevim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/zettelkasten-method-plugin-for-spacevim/</guid>
        
        <category>neovim</category>
        
        <category>zettelkasten</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>《好东西》观后感</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#关于善意的谎言&quot; id=&quot;markdown-toc-关于善意的谎言&quot;&gt;关于“善意的谎言”&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#一些其他想法&quot; id=&quot;markdown-toc-一些其他想法&quot;&gt;一些其他想法&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

新的工作环境感觉不是想象中那么理想，但是也在努力去适应。
最近感觉也比较压抑，本来周末想去看的一部电影，因为一些事情耽搁了，今晚抽空一个人去电影院看了。

正如电影的名字一样，即便是生活很多时候不是很如意，但是有些人还是很善于发现身边的一些“好东西”。

可能是因为自己工作的原因，很多时候太过追求结果，而忽略了过程中一些美好的事情。

&lt;h3 id=&quot;关于善意的谎言&quot;&gt;关于“善意的谎言”&lt;/h3&gt;

曾今的我一直固执的认为谎言就是谎言，没有善恶之分，因为总有方式更好地呈现事实。
但很多时候，一些善意的谎言其实可以让事情变得更加简单。

&lt;h3 id=&quot;一些其他想法&quot;&gt;一些其他想法&lt;/h3&gt;

其实，说实在的，电影不是特别的好看，很多情节、对话太过于刻意。
就感觉正常的两个人对话，不该是这样，很多时候刻意的制造一些“鸡汤”类的说教，
或者刻意的制造一些搞笑的对话。

但是，其中确实有很多“鸡汤”值得去好好想想，比如：

1、小女孩上台表演前的那段对话，有时候因为害怕别人的眼光、说辞、看法，
而退缩，其实，这个社会上，在意你的人，真的没有你想象的那么多。
可能明天，他就会忘记你所做的事。

2、又比如小孩的作文，我最喜欢的、以及出现了两次的跟幻想相关的话题。
我觉得小孩子还没有这样的思想，更多的是电影呈现给观众的一些观点。
是的，即便是现在，后面的生活，还有很多年，你永远不会知道自己最喜欢的将会是什么，还是要保留一些幻想。
</description>
        <pubDate>Mon, 25 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/20241125/</link>
        <guid isPermaLink="true">https://wsdjeg.net/20241125/</guid>
        
        <category>movie</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>《重生》：揭穿人性假面</title>
        <description>周末跟家人们去看了一部电影，小朋友们选了柯南，我就去看了张家辉主演的《重生》。

&lt;style&gt;
  .image-gallery {
    overflow: auto;
    margin-left: -1% !important;
  }
  .image-gallery li {
    float: left;
    display: block;
    padding:3px 3px;
    width: 19%;
  }
  .image-gallery li a {
    text-align: center;
    text-decoration: none !important;
    color: #777;
  }
  .image-gallery li a span {
    display: block;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    padding: 3px 0;
  }
  .image-gallery li a img {
    width: 100%;
    display: block;
  }
&lt;/style&gt;

&lt;ul class=&quot;image-gallery&quot;&gt;
  
&lt;/ul&gt;

&lt;strong&gt;剧中角色:&lt;/strong&gt;

&lt;blockquote&gt;
  安渡（阮经天 饰）
&lt;/blockquote&gt;

安渡缉毒组小队长，被其舅舅安佩长期长期压抑不得势再加上自幼经历悲惨，造成了阴暗的性格，被权力、金钱迷失倒也正常。
人性这种东西其实很奇怪，不能去深究其好坏。

&lt;blockquote&gt;
  张耀（张家辉 饰）
&lt;/blockquote&gt;

张耀的剧情也算还能理解，想要在监狱里替换掉沙旺，并且通过各种检查，没有安渡他们的安排跟支持几乎不可能。

&lt;blockquote&gt;
  巴莱（马浴柯 饰）
&lt;/blockquote&gt;

完全没有想到的是南茜和巴莱也是也是提前安排好的碟中谍角色。

</description>
        <pubDate>Sun, 08 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/movie-review-go-for-broke/</link>
        <guid isPermaLink="true">https://wsdjeg.net/movie-review-go-for-broke/</guid>
        
        <category>movie</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>删除 Telegram 账号</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;!-- prettier-ignore-end --&gt;

前不久，删除了用了很久的 Telegram 账号 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@wsdjeg&lt;/code&gt;。

为了避免非本人使用该用户名带来不必要的麻烦，原来的用户名转移给了一个无管理员的公共的 Channel。

个人是非常抵触使用手机号注册和登录的软件，因为手机号实际上运营商是可以二次销售的。
大学期间至今，前面大概有三个手机号已经停机不用了，但是现在搜了下，居然有别人已经用它来注册了微信。

此外，如果提供足够的材料或者“特殊情况”下，运营商可以重新制作一张 SIM 卡，原 SIM 会废弃。
那么新卡就可以接受验证信息，这就意味着，对于账号的所有权，你没有绝对的控制权。

此外，删除 Telegram 另一个原因是在于自己，我想远离不必要的争执。不管是什么原因，有可能是对方问题。
也有可能是自己的问题。但是这些都并不重要，因为这种争执对于自己来说。似乎没有任何用处。只会徒增烦恼、浪费时间。

可能是因为匿名状态下更加肆无忌惮吧。
</description>
        <pubDate>Sat, 24 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/delete-telegram-account/</link>
        <guid isPermaLink="true">https://wsdjeg.net/delete-telegram-account/</guid>
        
        <category>telegram</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>Vim Script 的新语法</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#字符串的连接符&quot; id=&quot;markdown-toc-字符串的连接符&quot;&gt;字符串的连接符&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#函数的参数&quot; id=&quot;markdown-toc-函数的参数&quot;&gt;函数的参数&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#闭包closure&quot; id=&quot;markdown-toc-闭包closure&quot;&gt;闭包（closure）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

对于 Vim Script 的语法的认知似乎还停留在 《笨方法学 Vim Script》的年代，
在接触 Neovim 以及使用 Lua 写插件之前一直都是使用 Vim Script。
即使是现在部分插件为了兼容 Vim，任然会使用 Vim 脚本实现一个兼容版本。
随着 Vim 版本的更新，实际上以及引入了很多新的语法格式。

&lt;h2 id=&quot;字符串的连接符&quot;&gt;字符串的连接符&lt;/h2&gt;

查看了下自己以往写的 Vim 脚本，string 的连接符仍然是使用单个点，实际上 Vim 早就支持使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;..&lt;/code&gt; 符号来连接字符串。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;abc&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;def&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&quot; 可以改成&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;abc&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;def&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;函数的参数&quot;&gt;函数的参数&lt;/h2&gt;

在函数内部调用传入的参数，过往最常用的无外乎 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a:0&lt;/code&gt;、 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a:000&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a:foo&lt;/code&gt; 等等。

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a:&lt;/code&gt; 实际上是一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dict&lt;/code&gt; 变量, 可以看下具体包含哪些 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key&lt;/code&gt;:

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;so %&lt;/code&gt; 输出如下：
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{&apos;0&apos;: 1, &apos;000&apos;: [3], &apos;1&apos;: 3, &apos;y&apos;: 2, &apos;firstline&apos;: 1, &apos;x&apos;: 1, &apos;lastline&apos;: 2}
{&apos;0&apos;: 1, &apos;000&apos;: [3], &apos;1&apos;: 3, &apos;y&apos;: 2, &apos;firstline&apos;: 1, &apos;x&apos;: 1, &apos;lastline&apos;: 2}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

从上面的输出不难看出 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a:&lt;/code&gt; 字典变量中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key&lt;/code&gt; 包括:

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;: 可变参数数量, 可变参数是 1 个 3&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;000&lt;/code&gt;: 可变参数组成的列表&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;: 特定名称的参数&lt;/li&gt;
&lt;/ul&gt;

此外还有两个特殊 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key&lt;/code&gt; 值，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;firstline&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lastline&lt;/code&gt;, 这个是传入的 range, 同时这意味着在定义函数时，参数名称不可以是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;firstline&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lastline&lt;/code&gt;。
否则会有如下错误：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;E125: Illegal argument: firstline
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在 Vim 8.1.1310 中，增加了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;optional-function-argument&lt;/code&gt;, 具体写法如下：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{&apos;0&apos;: 0, &apos;000&apos;: [], &apos;y&apos;: 3, &apos;firstline&apos;: 1, &apos;x&apos;: 1, &apos;lastline&apos;: 1}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上面的输出可以看出，在调用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s:foo&lt;/code&gt; 函数时，虽然只传入了一个参数，但是在函数内部 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a:&lt;/code&gt; 任然有一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; key，其值为默认值 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3&lt;/code&gt;。

&lt;h2 id=&quot;闭包closure&quot;&gt;闭包（closure）&lt;/h2&gt;

闭包在其他很多编程语言里面都有类似的写法，可以理解为一个函数工厂，根据“环境变量”返回一个特定环境下的函数。
在 Vim 7.4.2120 中给 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:function&lt;/code&gt; 定义增加了 closure 属性。示例如下：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:xy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; closure
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;funcref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;s:xy&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

echo &lt;span class=&quot;nv&quot;&gt;s:a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
echo &lt;span class=&quot;nv&quot;&gt;s:b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

若不使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;closure&lt;/code&gt; 关键字，在函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s:xy&lt;/code&gt; 内部是无法调用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a:x&lt;/code&gt; 的。

其实，在 Lua 中也可以实现类似的功能：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上两种输出结果都是：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;4.0
8.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Wed, 21 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/new-syntax-for-vim-script/</link>
        <guid isPermaLink="true">https://wsdjeg.net/new-syntax-for-vim-script/</guid>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>龙迹之城散人玩家攻略</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#定期活动&quot; id=&quot;markdown-toc-定期活动&quot;&gt;定期活动&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#第一天开区&quot; id=&quot;markdown-toc-第一天开区&quot;&gt;第一天：开区&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#第八天狂暴降临&quot; id=&quot;markdown-toc-第八天狂暴降临&quot;&gt;第八天：狂暴降临&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#第十五天末日降临&quot; id=&quot;markdown-toc-第十五天末日降临&quot;&gt;第十五天：末日降临&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#第二十二天秒杀直购&quot; id=&quot;markdown-toc-第二十二天秒杀直购&quot;&gt;第二十二天：秒杀直购&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#第二十九天神罚套装&quot; id=&quot;markdown-toc-第二十九天神罚套装&quot;&gt;第二十九天：神罚套装&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#第三十六天炎阳套装&quot; id=&quot;markdown-toc-第三十六天炎阳套装&quot;&gt;第三十六天：炎阳套装&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#周年庆活动&quot; id=&quot;markdown-toc-周年庆活动&quot;&gt;周年庆活动&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#装备合成技巧&quot; id=&quot;markdown-toc-装备合成技巧&quot;&gt;装备合成技巧&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#符文提升技巧&quot; id=&quot;markdown-toc-符文提升技巧&quot;&gt;符文提升技巧&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#龙子提升技巧&quot; id=&quot;markdown-toc-龙子提升技巧&quot;&gt;龙子提升技巧&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#异兽提升&quot; id=&quot;markdown-toc-异兽提升&quot;&gt;异兽提升&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#兽神出战&quot; id=&quot;markdown-toc-兽神出战&quot;&gt;兽神出战&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

已经不是第一次玩传奇类氪金游戏了，基本上都是前期氪金买的东西，
后期一文不值，并且有可能可以白嫖。意味着，前期氪金很多，
后期跟不上氪的话，会很容易被追上。

这里记录一下散人（微氪）玩家的玩法。

&lt;h2 id=&quot;定期活动&quot;&gt;定期活动&lt;/h2&gt;

这游戏根据天数，会定期出活动，这里根据我自己的目前所在区服来更新。有可能与老区或者新区有不一样的。

&lt;h3 id=&quot;第一天开区&quot;&gt;第一天：开区&lt;/h3&gt;

新建角色选法师、或者道士，战士不适合微氪玩。
赞助拿前三个赞助就够了，在吃 10 元红包，凑满 100，领取 98 连冲奖励。

主线任务、红包任务做完。任务做完，灵符一分不用，
只买第一天两个赞助对应的称号跟衣服，第八天这些灵符会返回来。

第二到第五天 每天吃100红包，灵符传奇币全攒着，
武魂只升级到10， 神器2。

异兽、符文、英雄之心，不要合成，材料全留着。

&lt;h3 id=&quot;第八天狂暴降临&quot;&gt;第八天：狂暴降临&lt;/h3&gt;

以前第八天是灵符抽技能活动，现在改版了，变成了狂暴直氪，
前四个任务是额度到了就可以领取，第五个是需要抽奖抽到一个才能领取。
微氪抽奖就算了，这次我只开通了第四个赞助，拿了一个狂暴装备，
同时天赋里面可以用98万灵符购买紫电神雷技能。

&lt;h3 id=&quot;第十五天末日降临&quot;&gt;第十五天：末日降临&lt;/h3&gt;

末日是直氪卷轴开岛上箱子。500 元可以拿三件末日、
一个狐狸、四个特权。可以五天每天 100 元直氪末日卷轴，
顺便拿 98 元连冲奖励及 5 天连冲装扮。

&lt;ul&gt;
  &lt;li&gt;第一岛选“元宝专享”&lt;/li&gt;
  &lt;li&gt;第二岛选“遗迹特权”&lt;/li&gt;
  &lt;li&gt;第三岛选末日&lt;/li&gt;
  &lt;li&gt;第四岛选“灵石专享”&lt;/li&gt;
  &lt;li&gt;第五岛选末日&lt;/li&gt;
  &lt;li&gt;第六岛选狐狸战灵&lt;/li&gt;
  &lt;li&gt;第七岛选“魔石专享”&lt;/li&gt;
  &lt;li&gt;第八岛选末日&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;第二十二天秒杀直购&quot;&gt;第二十二天：秒杀直购&lt;/h3&gt;

秒杀活动有点类似与狂暴，前四个任务也是五百额度，
包括：兽神装备、妖狱特权、三件秒杀、三个技能觉醒。

&lt;h3 id=&quot;第二十九天神罚套装&quot;&gt;第二十九天：神罚套装&lt;/h3&gt;

神罚套装的活动跟第十五天的末日活动几乎是一样的，因此也是 500 元拿三件神罚、
三个特权、一个精灵幻化、一件兽神装备任选，也是五天每天 100 元直氪末日卷轴，
顺便拿 98 元连冲奖励及 5 天连冲装扮。

&lt;ul&gt;
  &lt;li&gt;第一岛选“灵符加成”&lt;/li&gt;
  &lt;li&gt;第二岛选“禁地双倍”&lt;/li&gt;
  &lt;li&gt;第三岛选神罚&lt;/li&gt;
  &lt;li&gt;第四岛选“传奇专享”&lt;/li&gt;
  &lt;li&gt;第五岛选神罚&lt;/li&gt;
  &lt;li&gt;第六岛选圣光精灵&lt;/li&gt;
  &lt;li&gt;第七岛选“兽神装备任选”&lt;/li&gt;
  &lt;li&gt;第八岛选神罚&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;第三十六天炎阳套装&quot;&gt;第三十六天：炎阳套装&lt;/h3&gt;

炎阳套装和前面的秒杀类似，前四个任务是五百，包括：8阶军装刀、“传奇回收”、“经验专享”、“传奇回收Ⅱ”、超级幸运、三件炎阳。

&lt;h3 id=&quot;周年庆活动&quot;&gt;周年庆活动&lt;/h3&gt;

完成每日任务，周年庆商店里面的东西可以全部兑换出来，包括六个英雄、一个狐狸、苍血真龙皓月各一件，升星石等等。

&lt;h2 id=&quot;装备合成技巧&quot;&gt;装备合成技巧&lt;/h2&gt;

每个部位三个属性，锻造时，两个单字锻造成双字，双字+单字锻造成终极。

锻造时左边为主装备、右边为附装备，锻造失败附装备损毁。

因此稀有属性单字，或者包含稀有属性的双字应该放在左边，与稀有属性匹配的双字要直接熔炼掉。

这样才能最大化装备收益。

下面列出装备各部位属性，三个字自上而下稀有程度递减：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;武器&lt;/th&gt;
      &lt;th&gt;属性&lt;/th&gt;
      &lt;th&gt;匹配&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;血&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;吸血&lt;/td&gt;
      &lt;td&gt;爆裂 （爆 + 攻），全熔炼&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;爆&lt;/td&gt;
      &lt;td&gt;暴击几率&lt;/td&gt;
      &lt;td&gt;怒血 （血 + 攻）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;攻&lt;/td&gt;
      &lt;td&gt;攻击增伤&lt;/td&gt;
      &lt;td&gt;破天 （血 + 爆）&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;衣服&lt;/th&gt;
      &lt;th&gt;属性&lt;/th&gt;
      &lt;th&gt;匹配&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;防&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;物伤减免、魔伤减免&lt;/td&gt;
      &lt;td&gt;不灭（抗 + 反）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;抗&lt;/td&gt;
      &lt;td&gt;暴击抵抗&lt;/td&gt;
      &lt;td&gt;金刚&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;反&lt;/td&gt;
      &lt;td&gt;反伤&lt;/td&gt;
      &lt;td&gt;神体&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;头盔&lt;/th&gt;
      &lt;th&gt;属性&lt;/th&gt;
      &lt;th&gt;匹配&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;防&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;物伤减免、魔伤减免&lt;/td&gt;
      &lt;td&gt;天命（护 + 闪）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;护&lt;/td&gt;
      &lt;td&gt;破甲抵抗&lt;/td&gt;
      &lt;td&gt;玄体&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;闪&lt;/td&gt;
      &lt;td&gt;吸血抵抗&lt;/td&gt;
      &lt;td&gt;龙体&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;项链&lt;/th&gt;
      &lt;th&gt;属性&lt;/th&gt;
      &lt;th&gt;匹配&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;血&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;吸血&lt;/td&gt;
      &lt;td&gt;斩神（破 + 攻），全熔炼&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;破&lt;/td&gt;
      &lt;td&gt;无视双防&lt;/td&gt;
      &lt;td&gt;怒血（血 + 攻）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;攻&lt;/td&gt;
      &lt;td&gt;攻击增伤&lt;/td&gt;
      &lt;td&gt;弑天（血 + 破）&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;手镯&lt;/th&gt;
      &lt;th&gt;属性&lt;/th&gt;
      &lt;th&gt;匹配&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;固&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;暴伤减免&lt;/td&gt;
      &lt;td&gt;天怒（破 + 闪）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;破&lt;/td&gt;
      &lt;td&gt;无视双防&lt;/td&gt;
      &lt;td&gt;无双&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;闪&lt;/td&gt;
      &lt;td&gt;吸血抵抗&lt;/td&gt;
      &lt;td&gt;爆破&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;戒指&lt;/th&gt;
      &lt;th&gt;属性&lt;/th&gt;
      &lt;th&gt;匹配&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;攻&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;攻击增伤&lt;/td&gt;
      &lt;td&gt;戮魔（爆 + 狂）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;爆&lt;/td&gt;
      &lt;td&gt;暴击几率&lt;/td&gt;
      &lt;td&gt;灭神&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;狂&lt;/td&gt;
      &lt;td&gt;暴击增伤&lt;/td&gt;
      &lt;td&gt;破天&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;鞋子&lt;/th&gt;
      &lt;th&gt;属性&lt;/th&gt;
      &lt;th&gt;匹配&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;防&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;物伤减免、魔伤减免&lt;/td&gt;
      &lt;td&gt;破军&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;御&lt;/td&gt;
      &lt;td&gt;暴击抵抗&lt;/td&gt;
      &lt;td&gt;真魂（防 + 护）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;护&lt;/td&gt;
      &lt;td&gt;破甲抵抗&lt;/td&gt;
      &lt;td&gt;神体&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;腰带&lt;/th&gt;
      &lt;th&gt;属性&lt;/th&gt;
      &lt;th&gt;匹配&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;防&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;物伤减免、魔伤减免&lt;/td&gt;
      &lt;td&gt;天命（御 + 护）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;御&lt;/td&gt;
      &lt;td&gt;暴击抵抗&lt;/td&gt;
      &lt;td&gt;不灭&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;护&lt;/td&gt;
      &lt;td&gt;破甲抵抗&lt;/td&gt;
      &lt;td&gt;混元&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;符文提升技巧&quot;&gt;符文提升技巧&lt;/h2&gt;

符文一共有八个，按照最低级别提供套装属性，符文主要来自于试炼之地的boss、禁地。

&lt;ul&gt;
  &lt;li&gt;试炼之地：乾，坤，离，坎，兑，&lt;/li&gt;
  &lt;li&gt;禁地：震，艮，巽&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;龙子提升技巧&quot;&gt;龙子提升技巧&lt;/h2&gt;

龙子主要来自于龙眠神殿 Boss、禁地，

&lt;ul&gt;
  &lt;li&gt;禁地：睚眦、蒲牢、霸下&lt;/li&gt;
  &lt;li&gt;龙眠神殿：其他 6 个&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;异兽提升&quot;&gt;异兽提升&lt;/h2&gt;

异兽主要来自于灵犀 Boss 爆落，活动里面七天登录送、60 连重送任选：

&lt;ul&gt;
  &lt;li&gt;七天登录送：圣兽白虎、雪域狂狮、荆棘地龙、圣兽青龙, 地龙比白虎和狂狮高一阶，青龙比地龙高一阶&lt;/li&gt;
  &lt;li&gt;任选开：暗殿麒麟&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;兽神出战&quot;&gt;兽神出战&lt;/h2&gt;

妖狱进地图的条件依赖于出战的兽神级别，优先让最高级出战，点击兽神，会显示兽神装扮是否齐全，提示是否被其他兽神装备了。

出战最高级别兽神后，进入地图，只打最高级别的boss。
</description>
        <pubDate>Wed, 21 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/20240821/</link>
        <guid isPermaLink="true">https://wsdjeg.net/20240821/</guid>
        
        <category>game</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>使用 GitHub 进行身份验证时要小心</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#授权登录时需要的权限&quot; id=&quot;markdown-toc-授权登录时需要的权限&quot;&gt;授权登录时需要的权限&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#查看-github-账户已授权网站&quot; id=&quot;markdown-toc-查看-github-账户已授权网站&quot;&gt;查看 Github 账户已授权网站&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#国内版-github&quot; id=&quot;markdown-toc-国内版-github&quot;&gt;国内版 Github?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

很早以前，我注册过一个叫做“黑客派”的论坛，后来这个论坛改名为“链滴”。

当时论坛提供了使用 Github 账号授权登录，由于早期并未注意过 GitHub 登录授权的权限问题。
被站长直接控制 Github 账号去执行 star 和 follow 操作，相关帖子可以看：https://v2ex.com/t/534800

谷歌搜索已无主站入口：

&lt;img src=&quot;https://img.spacevim.org/ld-1.png&quot; alt=&quot;&quot; /&gt;

直接搜索最新网址，发现一篇道歉信排名靠前，可想此事当时影响挺大的。

&lt;img src=&quot;https://img.spacevim.org/ld-2.png&quot; alt=&quot;&quot; /&gt;

但是非注册用户点击却无法阅读，啥意思？只给注册用户道歉？

&lt;img src=&quot;https://img.spacevim.org/ld-3.png&quot; alt=&quot;&quot; /&gt;

使用 web achive 服务拉取到道歉信内容：

&lt;img src=&quot;https://img.spacevim.org/ld-4.png&quot; alt=&quot;&quot; /&gt;

最近我尝试登录这个账号并提交账号注销申请，按照他的网站说明：来去自由·关于支持永久停用账号。

&lt;img src=&quot;../images/ld246_post.png&quot; alt=&quot;关于支持永久停用账号&quot; /&gt;

但是似乎并不是那么回事。

申请注销时提示更新失败 - Can not deactivate moderator account。于是只能手动将自己以往再次网站发的帖子全部改成：

&lt;img src=&quot;../images/ld_delete_old_post.png&quot; alt=&quot;old_post&quot; /&gt;

在体用账号帖子留言后，账号被封禁，而不是被停用。

&lt;img src=&quot;../images/ld246_comment.png&quot; alt=&quot;&quot; /&gt;
&lt;img src=&quot;../images/ld246.png&quot; alt=&quot;&quot; /&gt;

最后，我们再看下链滴作者 D 的博客 https://88250.b3log.org 评论系统，使用 Github 登录时所需要的权限：

&lt;img src=&quot;../images/88250_blog.png&quot; alt=&quot;&quot; /&gt;

&lt;h2 id=&quot;授权登录时需要的权限&quot;&gt;授权登录时需要的权限&lt;/h2&gt;

在初次注册登录时，都会出现以下界面，可以点击右侧红框下拉按钮，展开所有的权限。实际上，如果仅用于注册网站，需要一个唯一的注册ID的话，获取邮箱地址的权限就足够了。
图片中显示了 julia 语言论坛授权登录权限信息：

&lt;img src=&quot;https://img.spacevim.org/ld-5.png&quot; alt=&quot;&quot; /&gt;

&lt;h2 id=&quot;查看-github-账户已授权网站&quot;&gt;查看 Github 账户已授权网站&lt;/h2&gt;

在 Github 账户设置界面依次点击：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Integrations&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Applications&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Authorized OAuth Apps&lt;/code&gt;:

&lt;img src=&quot;https://img.spacevim.org/ld-6.png&quot; alt=&quot;&quot; /&gt;

如果需要看各自的授权权限点开即可查看:

&lt;img src=&quot;https://img.spacevim.org/ld-7.png&quot; alt=&quot;&quot; /&gt;

如果认为该权限太高，可以点击右侧的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Revoke access&lt;/code&gt;。

&lt;h2 id=&quot;国内版-github&quot;&gt;国内版 Github?&lt;/h2&gt;

最后，我们来看看号称国内版 Github 的码云使用 Github 授权时需要的权限：

&lt;img src=&quot;https://img.spacevim.org/ld-8.png&quot; alt=&quot;&quot; /&gt;

请问要读&lt;strong&gt;写&lt;/strong&gt;用户的 Followers 做什么？
</description>
        <pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/be-careful-when-authenticating-with-github/</link>
        <guid isPermaLink="true">https://wsdjeg.net/be-careful-when-authenticating-with-github/</guid>
        
        <category>github</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>请停止复制我的个人网站</title>
        <description>今天使用 Google 搜索自己之前发过的一篇文章“停用 v2ex 账号”，
发现搜索结果如下。奇怪的是，
有一个域名为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jbwqfy.com&lt;/code&gt; 的网站居然是全站复制了我的个人博客。

&lt;img src=&quot;https://img.spacevim.org/google-delete-v2ex.png&quot; alt=&quot;google result&quot; /&gt;

打开其首页，我今日刚发的文章他都有，基本上是实时同步了，目前无法查明原因。

&lt;img src=&quot;https://img.spacevim.org/jbwqfy-home.png&quot; alt=&quot;jbwqfy home&quot; /&gt;

whois 查询结果显示如下，并没有什么有效信息。

&lt;img src=&quot;https://img.spacevim.org/whois-jbwqfy.png&quot; alt=&quot;whois jbwqfy&quot; /&gt;
</description>
        <pubDate>Sun, 11 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/stop-copy-my-static-website/</link>
        <guid isPermaLink="true">https://wsdjeg.net/stop-copy-my-static-website/</guid>
        
        <category>jekyll</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>从 GitHub Page 切换至 Cloudflare Page</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#新建-cloudflare-page&quot; id=&quot;markdown-toc-新建-cloudflare-page&quot;&gt;新建 Cloudflare Page&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#使用最新版-jekyll-及-插件&quot; id=&quot;markdown-toc-使用最新版-jekyll-及-插件&quot;&gt;使用最新版 Jekyll 及 插件&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#自定义域名&quot; id=&quot;markdown-toc-自定义域名&quot;&gt;自定义域名&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

大概是 2023 年 9 月份，将网站从 &lt;a href=&quot;../Migrate-from-GitHub-to-GitLab/&quot;&gt;Github Page 服务切换到了 Cloudflare Page&lt;/a&gt;。
一开始切换的原因是因为 Github 强制用户使用两步验证才能登录，失去了对 Github 账号的访问权限，
因此将网站移到了 Cloudflare Page 服务上。

&lt;h2 id=&quot;新建-cloudflare-page&quot;&gt;新建 Cloudflare Page&lt;/h2&gt;

登录 Cloudflare 后，在左侧点击 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Workers &amp;amp; Pages&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Create&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Connect to Git&lt;/code&gt;, 选择对应的仓库，
值得开心的是这里可以选择私有仓库。Github Page 服务免费用户无法使用私有仓库托管 Jekyll 静态网站。

构建设定：

&lt;ul&gt;
  &lt;li&gt;Build command: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundle exec jekyll build&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Build output directory: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/_site&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Root directory: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/docs&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Build comments on pull requests: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enabled&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;使用最新版-jekyll-及-插件&quot;&gt;使用最新版 Jekyll 及 插件&lt;/h2&gt;

原先使用的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;github-pages&lt;/code&gt; 对应的 Jekyll 版本太老，语法高亮的插件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rouge&lt;/code&gt; 也非常老旧。
在这里既然已经手动执行命令构建，那么可以使用一些比较新的插件，而不受 Github Page 的限制。
修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docs/Gemfile&lt;/code&gt; 为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;source &quot;https://rubygems.org&quot;
gem &quot;jekyll&quot;
gem &apos;jekyll-redirect-from&apos;
gem &apos;rouge&apos;, &apos;~&amp;gt; 4.2&apos;
gem &apos;jekyll-paginate&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;自定义域名&quot;&gt;自定义域名&lt;/h2&gt;

原先购买的域名已经转移到了 Cloudflare 上面了，这样一来域名的解析及网站的托管都在同一个平台，也方便管理。
</description>
        <pubDate>Sun, 11 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/from-github-page-to-cloudflare-page/</link>
        <guid isPermaLink="true">https://wsdjeg.net/from-github-page-to-cloudflare-page/</guid>
        
        <category>jekyll</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Vim9Script 与 Lua 的速度比较</title>
        <description>前面写过一篇&lt;a href=&quot;../rewrite-spacevim-builtin-plugin-using-lua/&quot;&gt;Lua 与 VimL 速度比较的文章&lt;/a&gt;，
里面对 Lua 与 VimL 脚本计算速度做了比较。随着 Vim 的更新并且推出了新的脚本语言 Vim9Script，
也想看一下这个新的脚本语言写法及执行效率到底如何。

任然参考上一篇文章中的比较方式，Vim9Script 实现的函数如下：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;vim9script&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; V9Fibo&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;N&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  var start &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reltime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  var &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str2nr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;N&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  var &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
    var &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
    var &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;73&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
      var tmp &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; tmp
    &lt;span class=&quot;k&quot;&gt;endwhile&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endwhile&lt;/span&gt;
  var sec &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reltimefloat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reltime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;start&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  echo &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Vim9Fibo(%s): %.6g sec&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; N&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; sec&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;enddef&lt;/span&gt;

defcompile

command&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;nargs&lt;span class=&quot;p&quot;&gt;=+&lt;/span&gt; TestV9Func V9Fibo&lt;span class=&quot;p&quot;&gt;(&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

新建一个 vim 文件，写入上述内容。使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:so %&lt;/code&gt; 载入脚本，分别执行如下测试命令：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:TestV9Func 1000
:TestV9Func 10000000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

本地测试结果：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Vim9Fibo(1000): 0.007455 sec
Vim9Fibo(10000000): 69.937198 sec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在前一篇文章中比较的是 Vim Script 和 Lua 的速度，其结果是：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Fibo(1000): 0.410364 sec
Fibo(10000000): 1470.280914 sec
LuaFibo(1000): 9.052000e-4 sec
LuaFibo(10000000): 1.235385 sec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

测试结果不难看出，Vim9Script 相较于老版本的 Vim script 确实有很大的速度提升。
计算参数1000时，从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.41s&lt;/code&gt; 提升到了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.0074s&lt;/code&gt;；
计算参数一千万时，从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1470s&lt;/code&gt; 提升到了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;69s&lt;/code&gt;。
但是相较于 Lua 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9.0e-4s&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.23s&lt;/code&gt; 的测试结果，还是相差太多。
</description>
        <pubDate>Sat, 10 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/speed-comparison-between-vim9script-and-lua/</link>
        <guid isPermaLink="true">https://wsdjeg.net/speed-comparison-between-vim9script-and-lua/</guid>
        
        <category>neovim</category>
        
        <category>vim</category>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Neovim 和 Vim 插件管理器的实现逻辑</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#插件的本质&quot; id=&quot;markdown-toc-插件的本质&quot;&gt;插件的本质&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#目录结构及载入时机&quot; id=&quot;markdown-toc-目录结构及载入时机&quot;&gt;目录结构及载入时机&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#autoload-目录&quot; id=&quot;markdown-toc-autoload-目录&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoload/&lt;/code&gt; 目录&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#plugin-目录&quot; id=&quot;markdown-toc-plugin-目录&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugin/&lt;/code&gt; 目录&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#ftplugin-目录&quot; id=&quot;markdown-toc-ftplugin-目录&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ftplugin/&lt;/code&gt; 目录&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#懒加载的实现逻辑&quot; id=&quot;markdown-toc-懒加载的实现逻辑&quot;&gt;懒加载的实现逻辑&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#通过命令加载-on_cmd&quot; id=&quot;markdown-toc-通过命令加载-on_cmd&quot;&gt;通过命令加载 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_cmd&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#根据函数加载-on_func&quot; id=&quot;markdown-toc-根据函数加载-on_func&quot;&gt;根据函数加载 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_func&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#根据事件加载-on_event&quot; id=&quot;markdown-toc-根据事件加载-on_event&quot;&gt;根据事件加载 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_event&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#根据文件类型加载-on_ft&quot; id=&quot;markdown-toc-根据文件类型加载-on_ft&quot;&gt;根据文件类型加载 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_ft&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#根据按键加载-on_map&quot; id=&quot;markdown-toc-根据按键加载-on_map&quot;&gt;根据按键加载 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_map&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#总结&quot; id=&quot;markdown-toc-总结&quot;&gt;总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

Neovim 或者 Vim 的插件管理器有很多，最开始的时候我使用的是 &lt;a href=&quot;https://github.com/VundleVim/Vundle.vim&quot;&gt;Vundle.vim&lt;/a&gt;,
后来尝试过 &lt;a href=&quot;https://github.com/junegunn/vim-plug&quot;&gt;vim-plug&lt;/a&gt; 和 &lt;a href=&quot;https://github.com/Shougo/neobundle.vim&quot;&gt;neobundle.vim&lt;/a&gt;，
目前使用的是 &lt;a href=&quot;https://github.com/Shougo/dein.vim&quot;&gt;dein.vim&lt;/a&gt;。当然了，网上搜一下，其实还有很多其他的插件管理器，
然而并没有发现什么特别吸引我的功能，所以也就没有什么动力切换了。

相较于切换插件管理器，其实我更想好好研究一下插件管理器的实现逻辑，于是看了一些文档及插件管理器的源码，整理这篇文章。

&lt;h2 id=&quot;插件的本质&quot;&gt;插件的本质&lt;/h2&gt;

我所理解的 Vim 或者 Neovim 的插件本质是一系列的 Vim 文件按照一定的目录结构组织起来的集合。
Neovim 中增加了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugin/&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;color/&lt;/code&gt; 等目录下 lua 文件的识别。

不管是 Vim 还是 Neovim，插件管理器添加一个插件的本质就是将插件所在的目录加入到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runtimepath&lt;/code&gt; 选项，
所谓的懒加载（lazy load）实际上是在适当的时机下触发前面这一步骤。

所以，很早以前，还没有插件管理器时，很多时候只是将插件下载到某一个目录，并在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vimrc&lt;/code&gt; 中将目录添加到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runtimepath&lt;/code&gt; 中。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;set runtimepath+=/path/to/plugin_directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;目录结构及载入时机&quot;&gt;目录结构及载入时机&lt;/h2&gt;

阅读 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h runtimepath&lt;/code&gt; 可以看到标准的插件的目录结构包括：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;filetype.lua    filetypes
autoload/       automatically loaded scripts
colors/         color scheme files
compiler/       compiler files
doc/            documentation
ftplugin/       filetype plugins
indent/         indent scripts
keymap/         key mapping files
lang/           menu translations
lua/            lua modules
menu.vim        GUI menus
pack/           packages
parser/         treesitter syntax parsers
plugin/         plugin scripts
queries/        treesitter queries
rplugin/        remote-plugin scripts
spell/          spell checking files
syntax/         syntax files
tutor/          tutorial files
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在说明每一个目录的功能之前，我认为有必要了解一下 Vim 启动时的文件载入顺序。

假定，我们有一个 hello-vim 插件，其目录为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/wsdjeg/bundle/hello-vim&lt;/code&gt;，示例 vimrc 文件：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nocompatible&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rtp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;+=~&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/wsdjeg/&lt;/span&gt;bundle/hello&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;vim&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;filetype&lt;/span&gt; plugin &lt;span class=&quot;nb&quot;&gt;indent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;on&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;syntax&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;on&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当启动 Vim 时，它将逐行读取并执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vimrc&lt;/code&gt; 文件。其中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set rtp&lt;/code&gt; 这一行就是将插件 hello-vim 的目录加入到 runtimepath 内。

下一行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filetype plugin indent on&lt;/code&gt;，这个命令包含了三层意思：

&lt;ol&gt;
  &lt;li&gt;启动文件类型自动识别，比如打开 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.md&lt;/code&gt; 文件时，自动识别并设置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filetype&lt;/code&gt; 为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;markdown&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;设置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filetype&lt;/code&gt; 时，根据 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;filetype&lt;/code&gt; 的值，自动读取并执行 runtimepath 中每一个目录下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ftplugin/&lt;/code&gt; 子目录里对应的 vim 文件&lt;/li&gt;
  &lt;li&gt;设置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filetype&lt;/code&gt; 时，根据 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;filetype&lt;/code&gt; 的值，自动读取并执行 runtimepath 中每一个目录下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indent/&lt;/code&gt; 子目录里对应的 vim 文件&lt;/li&gt;
&lt;/ol&gt;

关于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:filetype&lt;/code&gt; 命令的使用，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :filetype-overview&lt;/code&gt; 显示如下帮助文档：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Overview:					*:filetype-overview*

command			detection	plugin		indent ~
:filetype on			on		unchanged	unchanged
:filetype off			off		unchanged	unchanged
:filetype plugin on		on		on		unchanged
:filetype plugin off		unchanged	off		unchanged
:filetype indent on		on		unchanged	on
:filetype indent off		unchanged	unchanged	off
:filetype plugin indent on	on		on		on
:filetype plugin indent off	unchanged	off		off

To see the current status, type: &amp;gt;
	:filetype
The output looks something like this: &amp;gt;
	filetype detection:ON  plugin:ON  indent:OFF
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

那么，使用以上的简单的 vimrc 启动 Vim 时，文件的载入顺序为：

&lt;ul&gt;
  &lt;li&gt;vimrc&lt;/li&gt;
  &lt;li&gt;~/wsdjeg/bundle/hello-vim/plugin/*.vim&lt;/li&gt;
&lt;/ul&gt;

如果 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello-vim/&lt;/code&gt; 目录下有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filetype.vim&lt;/code&gt; 文件，或者存在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ftdetect/&lt;/code&gt; 子目录，其内 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.vim&lt;/code&gt; 文件也会被执行。

&lt;h3 id=&quot;autoload-目录&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoload/&lt;/code&gt; 目录&lt;/h3&gt;

关于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoload/&lt;/code&gt; 内的 Vim 文件载入机制，我们来做这样一个测试：

文件名: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.SpaceVim.d/autoload/test_autoload.vim&lt;/code&gt;，假定 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.SpaceVim.d/&lt;/code&gt; 已经加入 runtimepath。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hi one&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; test_autoload#&lt;span class=&quot;k&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hi two&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hi three&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

启动 Vim 后，发现上述三句 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echom&lt;/code&gt; 语句都没有执行，这也说明了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoload&lt;/code&gt; 内的文件默认是不会自动执行的。
此时如果执行函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;call test_autoload#hi()&lt;/code&gt;。就会发现如下输出：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;hi one
hi three
hi two
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

注意下输出的顺序，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hi three&lt;/code&gt; 在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hi two&lt;/code&gt; 前面。
这是因为当调用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_autoload#hi()&lt;/code&gt; 函数时，Vim 是根据函数的名称，确认下函数是否已定义，如果未定义，
则去找到对应的 Vim 文件读取并逐行执行，执行完了后才会调用函数。

前面执行过了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;call test_autoload#hi()&lt;/code&gt; 函数后，如果再次调用。此时输出只会有一行：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;hi two
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

那么问题来了，如果我再次调用一个不存在的函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;call test_autoload#no()&lt;/code&gt; 函数，会发生什么呢？

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;hi one
hi three
E117: Unknown function: test_autoload#no
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

也很好理解，这个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_autoload#no()&lt;/code&gt; 函数未定义，
Vim 根据函数名称会再次去读取并逐行执行 Vim 文件，也就导致了 Vim 文件中的脚本被重复执行了。不受控的重复执行肯定不行的，那么如何规避呢？
可以像下面这样修改：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;s:loaded&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;finish&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&quot; 有很多插件喜欢用 g:plugin_xxx_loaded, 个人感觉，非必要不使用暴露给脚本外部的变量跟函数。&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:loaded&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hi one&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; test_autoload#&lt;span class=&quot;k&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hi two&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hi three&quot;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;plugin-目录&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugin/&lt;/code&gt; 目录&lt;/h3&gt;

在 Vim 启动时默认的配置文件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vimrc&lt;/code&gt; 读取完成后, 此时会对 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runtimepath&lt;/code&gt; 下每一个目录下的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugin/&lt;/code&gt; 子目录进行遍历。其内所有的 Vim 文件会被逐一读取并执行。
Neovim 增加了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugin/&lt;/code&gt; 目录下 lua 文件的支持。

&lt;h3 id=&quot;ftplugin-目录&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ftplugin/&lt;/code&gt; 目录&lt;/h3&gt;

这个目录就是 Vim 自带的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_ft&lt;/code&gt; 加载机制，当 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filetype&lt;/code&gt; 被设定时会自动载入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ftplugin/&amp;lt;filetype&amp;gt;.vim&lt;/code&gt;，Neovim 还支持 Lua 格式文件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ftplugin/&amp;lt;filetype&amp;gt;.lua&lt;/code&gt;。

&lt;h2 id=&quot;懒加载的实现逻辑&quot;&gt;懒加载的实现逻辑&lt;/h2&gt;

很多插件管理器都实现了一个叫做 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lazy load（懒加载）&lt;/code&gt;的功能，那么这个功能到底是如何实现，其本质逻辑是什么呢？

&lt;h3 id=&quot;通过命令加载-on_cmd&quot;&gt;通过命令加载 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_cmd&lt;/code&gt;&lt;/h3&gt;

当执行某个命令时加载，这种实现逻辑实际上新建一个新的命令，在命令中载入插件，并根据其参数再次调用命令。

比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;call dein#add(&apos;wsdjeg/FlyGrep.vim&apos;, {&apos;on_cmd&apos; : &apos;FlyGrep&apos;})&lt;/code&gt;

此时会定义如下命令：

&lt;a href=&quot;https://github.com/SpaceVim/SpaceVim/blob/f15e9ec6789c8ddb95da39f346489b26ed6193ff/bundle/dein.vim/autoload/dein/parse.vim#L342&quot;&gt;dein.vim/autoload/dein/parse.vim#L342&lt;/a&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:generate_dummy_commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;plugin&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; abort
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;dummy_commands &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; name &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;on_cmd
    &lt;span class=&quot;c&quot;&gt;&quot; Define dummy commands.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; raw_cmd &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;command &apos;&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;          \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-complete=customlist,dein#autoload#_dummy_complete&apos;&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;          \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos; -bang -bar -range -nargs=* &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; name
&lt;span class=&quot;se&quot;&gt;          \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&quot; &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; dein#autoload#_on_cmd&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;%s&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; %s&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;          \&lt;/span&gt;  &lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;bang&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;line1&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;line2&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&quot;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;          \&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;dummy_commands&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; raw_cmd&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;silent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;execute&lt;/span&gt; raw_cmd
  &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在上述例子中，FlyGrep.vim 插件载入之前，执行的命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:FlyGrep&lt;/code&gt; 实际上时调用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dein#autoload#_on_cmd&lt;/code&gt; 函数

&lt;h3 id=&quot;根据函数加载-on_func&quot;&gt;根据函数加载 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_func&lt;/code&gt;&lt;/h3&gt;

当调用插件的函数时动态载入插件，其实我感觉这个功能有点多余。因为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoload/&lt;/code&gt; 目录下的 Vim 脚本文件在 Vim 启动时是不会自动执行的。
只有在调用对应的函数时才会载入并执行。

可能是为了更加极致的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lazy load&lt;/code&gt;, 让非载入的插件完全隐藏吧。那么 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_func&lt;/code&gt; 这个功能到底是如何实现的呢？

(Neo)Vim 有一个事件叫做 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FuncUndefined&lt;/code&gt;，是在调用不存在的函数时触发. 下面是一段简单的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_func&lt;/code&gt; 实现。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:lazy_plugins&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; Plug&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;&quot; 直接 添加 rtp&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s:lazy_plugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:on_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:lazy_plugins&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;on_func &lt;span class=&quot;p&quot;&gt;=~&lt;/span&gt;# &lt;span class=&quot;nv&quot;&gt;a:f&lt;/span&gt;
      &lt;span class=&quot;c&quot;&gt;&quot; 载入路径 path 的插件&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
augroup test_on_func
  autocmd&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;
  autocmd &lt;span class=&quot;nb&quot;&gt;FuncUndefined&lt;/span&gt; * &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:on_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;afile&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
augroup END

&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; Plug&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;~/.SpaceVim.d/hello-vim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;on_func&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;hello#&apos;&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;根据事件加载-on_event&quot;&gt;根据事件加载 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_event&lt;/code&gt;&lt;/h3&gt;

（Neo）Vim 有很多事件（event），这些事件在特定的时机会被触发。根据事件加载指的是设置某些插件在特定的事件触发时再载入系统。
相较于前面的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_cmd&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_func&lt;/code&gt; 的实现，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_event&lt;/code&gt; 的实现相对简单一些，
仅仅是监控事件的发生与否，对于发生时的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;amatch&amp;gt;&lt;/code&gt; 及 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;afile&amp;gt;&lt;/code&gt; 不做判断。

以下为简单的实现逻辑:

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:lazy_plugins&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
augroup test_on_event
autocmd&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;
augroup END
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&quot; 载入路径为 path 的插件&lt;/span&gt;
endfuntion
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; Plug&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;has_key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;on_event&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; event &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;on_event
      exe &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;autocmd test_on_event %s call s:load(&quot;%s&quot;)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; event&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; Plug&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;~/.SpaceVim.d/hello-vim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;on_event&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;InsertEnter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;WinEnter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;根据文件类型加载-on_ft&quot;&gt;根据文件类型加载 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_ft&lt;/code&gt;&lt;/h3&gt;

根据文件类型加载插件，实际上可以理解为一种特殊的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_event&lt;/code&gt; 懒加载模式。前面也说到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_event&lt;/code&gt; 懒加载不判断触发事件时的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;amatch&amp;gt;&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;afile&amp;gt;&lt;/code&gt; 值。
而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_ft&lt;/code&gt; 模式的懒加载底层逻辑是只监听 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FileType&lt;/code&gt; 这一种事件，并且在事件触发时判断 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;amatch&amp;gt;&lt;/code&gt; 值。

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_ft&lt;/code&gt; 懒加载的简单实现代码如下：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:lazy_plugins&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
augroup test_on_ft
autocmd&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;
augroup END
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&quot; 载入路径为 path 的插件&lt;/span&gt;
endfuntion
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; Plug&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;has_key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &apos;on_ft&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ft&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;on_ft
      exe &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;autocmd test_on_ft FileType %s call s:load(&quot;%s&quot;)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; Plug&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;~/.SpaceVim.d/hello-vim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;on_ft&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;java&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;python&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;根据按键加载-on_map&quot;&gt;根据按键加载 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_map&lt;/code&gt;&lt;/h3&gt;

以下这段摘自 dein.vim 的源码：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:generate_dummy_mappings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;plugin&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; abort
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;dummy_mappings &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;items&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;on_map&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;t_dict ?
&lt;span class=&quot;se&quot;&gt;        \&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;on_map&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;        \&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; _&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; val &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;val&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\zs&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;        \&lt;/span&gt;                dein#util#_convert2list&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;val&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])]})&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;        \&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;on_map&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;        \&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; _&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; val &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;val&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;t_list ?
&lt;span class=&quot;se&quot;&gt;        \&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;val&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\zs&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; val&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;x&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;val&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;modes&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; mappings&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;items&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; mappings &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;Plug&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;c&quot;&gt;&quot; Use plugin name.&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; mappings &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;Plug&amp;gt;(&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;normalized_name&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;stridx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;normalized_name&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; The plugin mappings may use &quot;_&quot; instead of &quot;-&quot;.&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;mappings&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;Plug&amp;gt;(&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;              \&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;substitute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;normalized_name&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;-&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;_&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;g&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; mapping &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; mappings
      &lt;span class=&quot;c&quot;&gt;&quot; Define dummy mappings.&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; prefix &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;dein#autoload#_on_map(%s, %s,&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;            \&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;substitute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;mapping&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;lt&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;g&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;            \&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; modes
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; raw_map &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;noremap &amp;lt;unique&amp;gt;&amp;lt;silent&amp;gt; &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;mapping
&lt;span class=&quot;se&quot;&gt;              \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;c&apos;&lt;/span&gt; ? &lt;span class=&quot;s2&quot;&gt;&quot; \&amp;lt;C-r&amp;gt;=&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;              \&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;i&apos;&lt;/span&gt; ? &lt;span class=&quot;s2&quot;&gt;&quot; \&amp;lt;C-o&amp;gt;:call &quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; :\&amp;lt;C-u&amp;gt;call &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;              \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; prefix &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;)&amp;lt;CR&amp;gt;&apos;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;dummy_mappings&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; mapping&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; raw_map&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;silent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;execute&lt;/span&gt; raw_map
      &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

不难看出，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_map&lt;/code&gt; 的实现机制跟 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_cmd&lt;/code&gt; 有点类似，实际上时定义了新的快捷键映射，触发时去调用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dein#autoload#on_map&lt;/code&gt; 函数。
再在这个函数内载入对应的插件，载入完成后使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;feedkey()&lt;/code&gt; 函数去模拟按下触发的快捷键映射。

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

本文主要介绍了 (neo)vim 插件的基本目录结构以及各个目录下文件的载入机制。
充分利用好这些机制后，即便是没有使用懒加载机制的情况下也可以大大的提高插件的初始化体验。
除此之外，本文还简单介绍了目前常见的几种赖加载机制的实现底层原理。

最后，说明一下，文中示例代码仅限于体现功能实现的基本逻辑，并未做额外的条件判断及错误捕获，并不适用于直接使用。
</description>
        <pubDate>Thu, 08 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/the-implementation-logic-of-plugin-manager/</link>
        <guid isPermaLink="true">https://wsdjeg.net/the-implementation-logic-of-plugin-manager/</guid>
        
        <category>neovim</category>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>实时调整 Neovim 的颜色主题</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#需求背景&quot; id=&quot;markdown-toc-需求背景&quot;&gt;需求背景&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#早期功能实现&quot; id=&quot;markdown-toc-早期功能实现&quot;&gt;早期功能实现&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#在主题设定后方直接修改&quot; id=&quot;markdown-toc-在主题设定后方直接修改&quot;&gt;在主题设定后方直接修改&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#使用-colorscheme-事件调用覆写函数&quot; id=&quot;markdown-toc-使用-colorscheme-事件调用覆写函数&quot;&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ColorScheme&lt;/code&gt; 事件调用覆写函数。&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#使用-cpickernvim-实时调色&quot; id=&quot;markdown-toc-使用-cpickernvim-实时调色&quot;&gt;使用 cpicker.nvim 实时调色&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;需求背景&quot;&gt;需求背景&lt;/h2&gt;

如果日常使用 Neovim 较多的话，选择一个喜欢的颜色主题还是非常不错的。Github 上面有很多 Neovim 主题插件。
但是在使用过程中会遇到这样情况，比如：“我觉得这个主题某个字段高亮颜色看着不喜欢，想做一个微调”。
一般遇到这种情况大多数人会 Fork 仓库进行修改，或者在配置文件设定主题后方进行覆盖。

&lt;h2 id=&quot;早期功能实现&quot;&gt;早期功能实现&lt;/h2&gt;

以上的这个功能需求，其实很久以前就有了，早期我的解决方法非常简单, 有两种：

&lt;h3 id=&quot;在主题设定后方直接修改&quot;&gt;在主题设定后方直接修改&lt;/h3&gt;

早期的配置文件比较简单，我都是在主题设定后方直接修改的，比如：

&lt;div class=&quot;language-viml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;colorschem one
&lt;span class=&quot;k&quot;&gt;hi&lt;/span&gt; VertSplit guibg&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;#282828&lt;/span&gt; guifg&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;#181A1F&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这种修改方式也存在弊端，就是在启动 Neovim 后，如果执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:colorscheme&lt;/code&gt; 命令切换主题，那配置文件中的微调将不再生效。

&lt;h3 id=&quot;使用-colorscheme-事件调用覆写函数&quot;&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ColorScheme&lt;/code&gt; 事件调用覆写函数。&lt;/h3&gt;

&lt;div class=&quot;language-viml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;ColorScheme&lt;/span&gt; * &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:fix_colorscheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:fix_colorscheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&quot; 使用 g:colors_name 判断主题名称&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&quot; 再此使用 highlight 命令修改高亮组&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这就解决了前面提到的切换主题后不再生效的问题。但是调整的过着无法在 Vim 里面完成，可能需要借助外部的调色板，调整好后把 hex 值写进配置文件。

&lt;h2 id=&quot;使用-cpickernvim-实时调色&quot;&gt;使用 cpicker.nvim 实时调色&lt;/h2&gt;

前面&lt;a href=&quot;../neovim-plugin-cpicker/&quot;&gt;介绍过我的 cpicker.nvim 插件&lt;/a&gt;，随着这个插件做出来后，借助它的调色板，又实现了一个实时调整高亮组的功能。并且，调整的结果会存住下来。
重启 Neovim 后，对应的颜色主题的修改还任然存在。

操作步骤如下：

&lt;ol&gt;
  &lt;li&gt;将光标移动到需要调色的位置&lt;/li&gt;
  &lt;li&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:CpickerCursorChangeHighlight&lt;/code&gt; 命令调出调色板浮窗，此时调色板默认颜色就是刚刚光标所在位置前景色。&lt;/li&gt;
  &lt;li&gt;上下移动光标至对应元素，左右进行调整，此时背景窗口中原先的字段高亮也会跟着变化。&lt;/li&gt;
  &lt;li&gt;调整完成后，使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;q&lt;/code&gt; 按键关闭调色板浮窗。&lt;/li&gt;
&lt;/ol&gt;

到此时已经调整完成，如果重启 Neovim 后，对当前这个主题调整任然会生效。

我录制了一个修改颜色及重启 Neovim 并设定颜色主题的动画：

&lt;img src=&quot;https://img.spacevim.org/change-colorscheme.gif&quot; alt=&quot;scrollbar&quot; /&gt;

对于调整过的颜色主题，如果需要清除掉调整，只需要执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:CpickerClearColorPatch&lt;/code&gt; 命令。
</description>
        <pubDate>Sat, 03 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/patch-neovim-colorscheme-on-the-fly/</link>
        <guid isPermaLink="true">https://wsdjeg.net/patch-neovim-colorscheme-on-the-fly/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>悬浮滚动条插件 scrollbar.vim</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#插件简介&quot; id=&quot;markdown-toc-插件简介&quot;&gt;插件简介&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#问题反馈&quot; id=&quot;markdown-toc-问题反馈&quot;&gt;问题反馈&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#安装及使用&quot; id=&quot;markdown-toc-安装及使用&quot;&gt;安装及使用&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;插件简介&quot;&gt;插件简介&lt;/h2&gt;

今天给大家分享一下我的 “新” 插件: &lt;a href=&quot;https://github.com/wsdjeg/scrollbar.vim&quot;&gt;scrollbar.vim&lt;/a&gt;。

&lt;img src=&quot;https://img.spacevim.org/scrollbar-vim.png&quot; alt=&quot;scrollbar&quot; /&gt;

这是一个支持 Neovim 和 Vim 的悬浮滚动条插件，
使用的是 Neovim 的 floating windows 或者 Vim 的 popup windows 特性。
相关内容可以阅读: Neovim 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h api-floatwin&lt;/code&gt; 或者 Vim 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h popup-window&lt;/code&gt;。

之所以前面的新字加上引号，是因为实际上这个插件早在三年多前就已经在 &lt;a href=&quot;https://spacevim.org&quot;&gt;SpaceVim&lt;/a&gt; 中使用了，是参考 &lt;a href=&quot;https://github.com/Xuyuanp/scrollbar.nvim&quot;&gt;Xuyuanp/scrollbar.nvim&lt;/a&gt; 逻辑重新使用 Vim Script 实现的。

在 SpaceVim 仓库下执行：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Git log autoload/SpaceVim/plugins/scrollbar.vim&lt;/code&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;* f1617ae12 - Add scrollbar support (#3826) (Wang Shidong 3 years, 10 months ago)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

随着后来对该插件进行不断的完善，以及针对新版本的 Neovim 重新实现的一个新的 Lua 版本，
目前插件已经基本稳定，可以独立使用，其代码执行的基本逻辑如下：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;nvim-0.9.0&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;lua&lt;/span&gt; require&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;spacevim.plugin.scrollbar&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;show&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; SpaceVim#plugins#scrollbar#show&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;问题反馈&quot;&gt;问题反馈&lt;/h2&gt;

目前，插件的维护及开发还是在 SpaceVim 的
&lt;a href=&quot;https://github.com/SpaceVim/SpaceVim/tree/master/bundle/scrollbar.vim&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundle/scrollbar.vim&lt;/code&gt;&lt;/a&gt;
目录中，使用 Github Action 同步到单独的仓库以便于直接使用。

如果在使用过程中遇到问题，或者有新的想法建议，欢迎在 &lt;a href=&quot;https://github.com/SpaceVim/SpaceVim/issues&quot;&gt;issue tracker&lt;/a&gt; 留言反馈。

&lt;h2 id=&quot;安装及使用&quot;&gt;安装及使用&lt;/h2&gt;

如果你是 SpaceVim 用户，只需要在 ui 模块内启用 scrollbar 即可：

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;ui&apos;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;enable_scrollbar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

对于非 SpaceVim 用户，也可以使用你喜欢的插件管理器进行安装，比如：

&lt;ul&gt;
  &lt;li&gt;vim-plug&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Plug &apos;wsdjeg/scrollbar.vim&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;lazy.vim&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- lazy.nvim&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;wsdjeg/scrollbar.vim&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;VeryLazy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Tue, 30 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/floating-scrollbar-for-vim-and-neovim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/floating-scrollbar-for-vim-and-neovim/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>关于 Neovim 插件开发的指南</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;!-- prettier-ignore-end --&gt;

今天，在 Neovim 中文电报群有人分享了一个仓库 &lt;a href=&quot;https://github.com/nvim-neorocks/nvim-best-practices/tree/24e835c20e1d591751007093387a1fafa89ebbe8&quot;&gt;nvim-best-practices@24e835c&lt;/a&gt;，
是关于 Neovim 插件开发的一些“指南”，或者可以说是“建议”，当然我也回复了我的想法，抱歉，语言有些过激。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;花花里胡巧的限制，我只看了开头就看不下去了，举例，命令要分成子命令，
这个除了浪费一层判断，没啥用。本来只定义一个FooInstall命令，
实际上在底层c就已经判断出来对应的函数。结果按照他这样，
需要在viml或者lua这边判断下到底这个命令是做什么的
跟谷歌的viml style guide相比差远了。另外手机上打开毫无阅读体验可谈。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

起初本来不是特别在意，只在群里回复一下就算了，因为习惯每个人都有，只要 “can
work” 就没必要纠结对与错了，因为毕竟也不会影响到自己的习惯。
但是随着浏览发现，居然要把这一内容&lt;a href=&quot;https://github.com/neovim/neovim/pull/29073&quot;&gt;合并到 Neovim 主仓库&lt;/a&gt;。
那我觉得就对我自己包括后来的 Neovim 用户都会有很大的影响。
因此我觉得有必要针对这个指南，写一些东西了。

逐行看一下，因为 Pull Request 的分支的一直在变动，而且是 force push，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:(&lt;/code&gt;，因此原文在文章中有直接文字体现。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;*lua-plugin.txt*                     Nvim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h lua-plugin&lt;/code&gt; 很容易让人误解，也很难将内容与这个关键词联想在一起。
如果是针对于命令定义、按键映射定义的建议，那么就不局限于 Lua 了。
而且，这个不是某个 plugin 的文档，而是插件开发的建议，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h plugin-dev&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h plugin-dev-guide&lt;/code&gt; 感觉更加合适一些。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
                            NVIM REFERENCE MANUAL

		  Guide to developing Lua plugins for Nvim


                                       Type |gO| to see the table of contents.

==============================================================================
Introduction                                                       *lua-plugin*

This is a guide for getting started with Nvim plugin development. It is not
intended as a set of rules, but as a collection of recommendations for good
practices.

For a guide to using Lua in Nvim, please refer to |lua-guide|.

==============================================================================
Type safety                                            *lua-plugin-type-safety*

Lua, as a dynamically typed language, is great for configuration. It provides
virtually immediate feedback.
But for larger projects, this can be a double-edged sword, leaving your plugin
susceptible to unexpected bugs at the wrong time.

You can leverage LuaCATS https://luals.github.io/wiki/annotations/
annotations, along with lua-language-server https://luals.github.io/ to catch
potential bugs in your CI before your plugin&apos;s users do.

------------------------------------------------------------------------------
Tools						 *lua-plugin-type-safety-tools*

- lua-typecheck-action https://github.com/marketplace/actions/lua-typecheck-action
- luacheck https://github.com/lunarmodules/luacheck for additional linting

==============================================================================
User commands					     *lua-plugin-user-commands*

Many users rely on command completion to discover available user commands. If
a plugin pollutes the command namespace with lots of commands, this can
quickly become overwhelming.

Example:

- `FooAction1 {arg}`
- `FooAction2 {arg}`
- `FooAction3`
- `BarAction1`
- `BarAction2`

Instead of doing this, consider gathering subcommands under scoped commands
and implementing completions for each subcommand.

Example:

- `Foo action1 {arg}`
- `Foo action2 {arg}`
- `Foo action3`
- `Bar action1`
- `Bar action2`
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

对于这点，我其实是持否定态度的。命令在定义时，其执行内容与字符串名字已经进行了绑定。
在调用命令时，底层 c 逻辑就已经判断出要去执行哪一个函数。
如果使用子命令，无疑要增加一个命令功能的分析，显得有些浪费。
如果一个插件只提拱了有限的几个命令,
比如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FooInstall&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FooUninstall&lt;/code&gt;，很明显就可以看出这两个命令的功能，根本没必要使用子命令。

当然，什么样情况下建议使用子命令呢？当多个命令的字面内容非常接近且难以区分时时，比如：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FooInstall1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FooInstall2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

这种情况下，建议用子命令，比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FooInstall 1&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FooInstall 2&lt;/code&gt; 或者，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo
install 1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo install 2&lt;/code&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
------------------------------------------------------------------------------
Subcommand completions example   *lua-plugin-user-commands-completions-example*

In this example, we want to provide:

- Subcommand completions if the user has typed `:Foo ...`
- Argument completions if they have typed `:Foo {subcommand}`

First, define a type for each subcommand, which has:

- An implementation: A function which is called when executing the subcommand.
- An optional command completion callback, which takes the lead of the
  subcommand&apos;s arguments.

&amp;gt;lua
    ---@class FooSubcommand
    ---@field impl fun(args:string[], opts: table)
    ---@field complete? fun(subcmd_arg_lead: string): string[]
&amp;lt;
Next, we define a table mapping subcommands to their implementations and
completions:
&amp;gt;lua
    ---@type table&amp;lt;string, FooSubcommand&amp;gt;
    local subcommand_tbl = {
        action1 = {
            impl = function(args, opts)
              -- Implementation (args is a list of strings)
            end,
            -- This subcommand has no completions
        },
        action2 = {
            impl = function(args, opts)
                -- Implementation
            end,
            complete = function(subcmd_arg_lead)
                -- Simplified example
                local install_args = {
                    &quot;first&quot;,
                    &quot;second&quot;,
                    &quot;third&quot;,
                }
                return vim.iter(install_args)
                    :filter(function(install_arg)
                        -- If the user has typed `:Foo action2 fi`,
                        -- this will match &apos;first&apos;
                        return install_arg:find(subcmd_arg_lead) ~= nil
                    end)
                    :totable()
            end,
            -- ...
        },
    }
&amp;lt;
Then, create a Lua function to implement the main command:
&amp;gt;lua
    ---@param opts table :h lua-guide-commands-create
    local function foo_cmd(opts)
        local fargs = opts.fargs
        local subcommand_key = fargs[1]
        -- Get the subcommand&apos;s arguments, if any
        local args = #fargs &amp;gt; 1 and vim.list_slice(fargs, 2, #fargs) or {}
        local subcommand = subcommand_tbl[subcommand_key]
        if not subcommand then
            vim.notify(&quot;Foo: Unknown command: &quot; .. subcommand_key, vim.log.levels.ERROR)
            return
        end
        -- Invoke the subcommand
        subcommand.impl(args, opts)
    end
&amp;lt;
See also |lua-guide-commands-create|.

Finally, we register our command, along with the completions:
&amp;gt;lua
    -- NOTE: the options will vary, based on your use case.
    vim.api.nvim_create_user_command(&quot;Foo&quot;, foo_cmd, {
        nargs = &quot;+&quot;,
        desc = &quot;My awesome command with subcommand completions&quot;,
        complete = function(arg_lead, cmdline, _)
            -- Get the subcommand.
            local subcmd_key, subcmd_arg_lead = cmdline:match(&quot;^Foo[!]*%s(%S+)%s(.*)$&quot;)
            if subcmd_key
                and subcmd_arg_lead
                and subcommand_tbl[subcmd_key]
                and subcommand_tbl[subcmd_key].complete
            then
                -- The subcommand has completions. Return them.
                return subcommand_tbl[subcmd_key].complete(subcmd_arg_lead)
            end
            -- Check if cmdline is a subcommand
            if cmdline:match(&quot;^Foo[!]*%s+%w*$&quot;) then
                -- Filter subcommands that match
                local subcommand_keys = vim.tbl_keys(subcommand_tbl)
                return vim.iter(subcommand_keys)
                    :filter(function(key)
                        return key:find(arg_lead) ~= nil
                    end)
                    :totable()
            end
        end,
        bang = true, -- If you want to support ! modifiers
    })
&amp;lt;
==============================================================================
Keymaps							   *lua-plugin-keymaps*

Avoid creating keymaps automatically, unless they are not controversial. Doing
so can easily lead to conflicts with user |mapping|s.

NOTE: An example for uncontroversial keymaps are buffer-local |mapping|s for
      specific file types or floating windows.

A common approach to allow keymap configuration is to define a declarative DSL
https://en.wikipedia.org/wiki/Domain-specific_language via a `setup` function.

However, doing so means that

- You will have to implement and document it yourself.
- Users will likely face inconsistencies if another plugin has a slightly
  different DSL.
- |init.lua| scripts that call such a `setup` function may throw an error if
  the plugin is not installed or disabled.

As an alternative, you can provide |&amp;lt;Plug&amp;gt;| mappings to allow users to define
their own keymaps with |vim.keymap.set()|.

- This requires one line of code in user configs.
- Even if your plugin is not installed or disabled, creating the keymap won&apos;t
  throw an error.

Another option is to simply expose a Lua function or |user-commands|.

However, some benefits of |&amp;lt;Plug&amp;gt;| mappings over this are that you can

- Enforce options like `expr = true`.
- Expose functionality only for specific |map-modes|.
- Expose different behavior for different |map-modes| with a single |&amp;lt;Plug&amp;gt;|
  mapping, without adding impurity or complexity to the underlying Lua
  implementation.

NOTE: If you have a function that takes a large options table, creating lots
      of |&amp;lt;Plug&amp;gt;| mappings to expose all of its uses could become
      overwhelming. It may still be beneficial to create some for the most
      common ones.

------------------------------------------------------------------------------
Example					      *lua-plugin-plug-mapping-example*

In your plugin:
&amp;gt;lua
    vim.keymap.set(&quot;n&quot;, &quot;&amp;lt;Plug&amp;gt;(SayHello)&quot;, function()
        print(&quot;Hello from normal mode&quot;)
    end, { noremap = true })

    vim.keymap.set(&quot;v&quot;, &quot;&amp;lt;Plug&amp;gt;(SayHello)&quot;, function()
        print(&quot;Hello from visual mode&quot;)
    end, { noremap = true })
&amp;lt;
In the user&apos;s config:
&amp;gt;lua
    vim.keymap.set({&quot;n&quot;, &quot;v&quot;}, &quot;&amp;lt;leader&amp;gt;h&quot;, &quot;&amp;lt;Plug&amp;gt;(SayHello)&quot;)
&amp;lt;
==============================================================================
Initialization					    *lua-plugin-initialization*

Newcomers to Lua plugin development will often put all initialization logic in
a single `setup` function, which takes a table of options.
If you do this, users will be forced to call this function in order to use
your plugin, even if they are happy with the default configuration.

Strictly separated configuration and smart initialization allow your plugin to
work out of the box.

NOTE: A well designed plugin has minimal impact on startup time.
      See also |lua-plugin-lazy-loading|.

Common approaches to a strictly separated configuration are:

- A Lua function, e.g. `setup(opts)` or `configure(opts)`, which only overrides the
  default configuration and does not contain any initialization logic.
- A Vimscript compatible table (e.g. in the |vim.g| or |vim.b| namespace) that your
  plugin reads from and validates at initialization time.
  See also |lua-vim-variables|.

Typically, automatic initialization logic is done in a |plugin| or |ftplugin|
script. See also |&apos;runtimepath&apos;|.

==============================================================================
Lazy loading					      *lua-plugin-lazy-loading*

When it comes to initializing your plugin, assume your users may not be using
a plugin manager that takes care of lazy loading for you.
Making sure your plugin does not unnecessarily impact startup time is your
responsibility. A plugin&apos;s functionality may evolve over time, potentially
leading to breakage if users have to hack into the loading mechanisms.
Furthermore, a plugin that implements its own lazy initialization properly will
likely have less overhead than the mechanisms used by a plugin manager or user
to load that plugin lazily.

------------------------------------------------------------------------------
Defer `require` calls			*lua-plugin-lazy-loading-defer-require*

|plugin| scripts should not eagerly `require` Lua modules.

For example, instead of:
&amp;gt;lua
    local foo = require(&quot;foo&quot;)
    vim.api.nvim_create_user_command(&quot;MyCommand&quot;, function()
        foo.do_something()
    end, {
      -- ...
    })
&amp;lt;
which will eagerly load the `foo` module and any other modules it imports
eagerly, you can lazy load it by moving the `require` into the command&apos;s
implementation.
&amp;gt;lua
    vim.api.nvim_create_user_command(&quot;MyCommand&quot;, function()
        local foo = require(&quot;foo&quot;)
        foo.do_something()
    end, {
      -- ...
    })
&amp;lt;
NOTE: For a Vimscript alternative to `require`, see |autoload|.

NOTE: In case you are worried about eagerly creating user commands, autocommands
      or keymaps at startup:
      Plugin managers that provide abstractions for lazy-loading plugins on
      such events will need to create these themselves.

------------------------------------------------------------------------------
Filetype-specific functionality		     *lua-plugin-lazy-loading-filetype*

Consider making use of |filetype| for any functionality that is specific to a
filetype, by putting the initialization logic in a `ftplugin/{filetype}.lua`
script.

------------------------------------------------------------------------------
Example				     *lua-plugin-lazy-loading-filetype-example*

A plugin tailored to Rust development might have initialization in
`ftplugin/rust.lua`:
&amp;gt;lua
    if not vim.g.loaded_my_rust_plugin then
        -- Initialize
    end
    -- NOTE: Using `vim.g.loaded_` prevents the plugin from initializing twice
    -- and allows users to prevent plugins from loading
    -- (in both Lua and Vimscript).
    vim.g.loaded_my_rust_plugin = true

    local bufnr = vim.api.nvim_get_current_buf()
    -- do something specific to this buffer,
    -- e.g. add a |&amp;lt;Plug&amp;gt;| mapping or create a command
    vim.keymap.set(&quot;n&quot;, &quot;&amp;lt;Plug&amp;gt;(MyPluginBufferAction)&quot;, function()
        print(&quot;Hello&quot;)
    end, { noremap = true, buffer = bufnr, })
&amp;lt;
==============================================================================
Configuration				             *lua-plugin-configuration*

Once you have merged the default configuration with the user&apos;s config, you
should validate configs.

Validations could include:

- Correct types, see |vim.validate()|
- Unknown fields in the user config (e.g. due to typos).
  This can be tricky to implement, and may be better suited for a |health|
  check, to reduce overhead.

==============================================================================
Troubleshooting					   *lua-plugin-troubleshooting*

------------------------------------------------------------------------------
Health checks			       	    *lua-plugin-troubleshooting-health*

Provide health checks in `lua/{plugin}/health.lua`.

Some things to validate:

- User configuration
- Proper initialization
- Presence of Lua dependencies (e.g. other plugins)
- Presence of external dependencies

See also |vim.health| and |health-dev|.

------------------------------------------------------------------------------
Minimal config template             *lua-plugin-troubleshooting-minimal-config*

It can be useful to provide a template for a minimal configuration, along with
a guide on how to use it to reproduce issues.

==============================================================================
Versioning and releases                        *lua-plugin-versioning-releases*

Consider

- Using SemVer https://semver.org/ tags and releases to properly communicate
  bug fixes, new features, and breaking changes.
- Automating versioning and releases in CI.
- Publishing to luarocks https://luarocks.org, especially if your plugin
  has dependencies or components that need to be built; or if it could be a
  dependency for another plugin.

------------------------------------------------------------------------------
Further reading		       *lua-plugin-versioning-releases-further-reading*

- Luarocks &amp;lt;3 Nvim https://github.com/nvim-neorocks/sample-luarocks-plugin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

有点强推 Luarocks。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
------------------------------------------------------------------------------
Tools			                 *lua-plugin-versioning-releases-tools*

- luarocks-tag-release
  https://github.com/marketplace/actions/luarocks-tag-release
- release-please-action
  https://github.com/marketplace/actions/release-please-action
- semantic-release
  https://github.com/semantic-release/semantic-release
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这些内容写在 wiki 或者一些单独的文章里足够了，合并到 Neovim 文档里面显得有些过了。并不是每个人都用 git 或者 github。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
==============================================================================
Documentation                                        *lua-plugin-documentation*

Provide vimdoc (see |help-writing|), so that users can read your plugin&apos;s
documentation in Nvim, by entering `:h {plugin}` in |command-mode|.

------------------------------------------------------------------------------
Tools			                       *lua-plugin-documentation-tools*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上两个 tag 完全可以合并，每个内容太少了点，最后这一大段，看了满屏 tag。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
- panvimdoc https://github.com/kdheepak/panvimdoc

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Mon, 29 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/about-the-nvim-plugin-dev-guide/</link>
        <guid isPermaLink="true">https://wsdjeg.net/about-the-nvim-plugin-dev-guide/</guid>
        
        <category>neovim</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>Neovim 调色板插件 cpicker.nvim</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#启用插件&quot; id=&quot;markdown-toc-启用插件&quot;&gt;启用插件&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#操作界面&quot; id=&quot;markdown-toc-操作界面&quot;&gt;操作界面&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#后续计划&quot; id=&quot;markdown-toc-后续计划&quot;&gt;后续计划&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

因为偶尔需要修改 Neovim 的高亮，涉及到颜色调整，以往使用的是外部工具，来回切换非常麻烦。
也找了一些 Neovim/Vim 的插件，但是使用的感觉确实不尽如人意。因此，自己实现了一个简便版本的调色板插件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cpicker.nvim&lt;/code&gt;，
该插件存储于 &lt;a href=&quot;https://github.com/wsdjeg/cpicker.nvim&quot;&gt;Github&lt;/a&gt; 。

&lt;h2 id=&quot;启用插件&quot;&gt;启用插件&lt;/h2&gt;

可以使用任意插件管理器进行安装，比如我的 nvim-plug:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/cpicker.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;depends&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/logger.nvim&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/notify.nvim&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;操作界面&quot;&gt;操作界面&lt;/h2&gt;

&lt;img src=&quot;../images/cpicker.png&quot; alt=&quot;&quot; /&gt;

操作快捷键：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;按键&lt;/th&gt;
      &lt;th&gt;功能描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Left&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;减小光标下的值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;l&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Right&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;增加光标下的值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Enter&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;复制光标下的颜色值&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;后续计划&quot;&gt;后续计划&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;目前支持的格式包括：RGB、HSL、HSV、CMYK，计划再增加一些常用的格式。&lt;/li&gt;
  &lt;li&gt;增加颜色混合调整面板&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 14 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-plugin-cpicker/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-plugin-cpicker/</guid>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neovim 缓冲区（buffer）相关事件</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#获取可用事件列表&quot; id=&quot;markdown-toc-获取可用事件列表&quot;&gt;获取可用事件列表&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#事件的触发时机&quot; id=&quot;markdown-toc-事件的触发时机&quot;&gt;事件的触发时机&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#bufadd&quot; id=&quot;markdown-toc-bufadd&quot;&gt;BufAdd&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#bufnew&quot; id=&quot;markdown-toc-bufnew&quot;&gt;BufNew&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#bufnewfile&quot; id=&quot;markdown-toc-bufnewfile&quot;&gt;BufNewFile&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#测试示例&quot; id=&quot;markdown-toc-测试示例&quot;&gt;测试示例&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

最近在使用 SpaceVim 的标签栏（tabline）时发现，对于新增的空内容的缓冲区（buffer），标签栏上方并不会列出。
检查源码发现标签栏跟踪缓冲区新增的代码只监听了：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BufNewFile&lt;/code&gt; 跟 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BufReadPost&lt;/code&gt; 事件。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BufNewFile&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BufReadPost&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;schedule_wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_is_valid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;right_hide_bufs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;visiable_bufs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left_hide_bufs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;right_hide_bufs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tabline_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

测试发现 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:enew&lt;/code&gt; 命令及 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:new&lt;/code&gt; 命令并不会触发这两个事件。修改源码&lt;a href=&quot;https://github.com/SpaceVim/SpaceVim/commit/2b9fd5509495754a4e94d646ae94de289e0b0c8e&quot;&gt;增加监听 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BufNew&lt;/code&gt; 事件&lt;/a&gt;。

虽然问题是修复了，但是我觉得有必要整理下缓冲区相关事件的触发时机。

&lt;h2 id=&quot;获取可用事件列表&quot;&gt;获取可用事件列表&lt;/h2&gt;

可以使用命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:echo getcompletion(&apos;Buf&apos;, &apos;event&apos;)&lt;/code&gt; 快速查看当前 Neovim 版本支持的缓冲区事件列表。

&lt;h2 id=&quot;事件的触发时机&quot;&gt;事件的触发时机&lt;/h2&gt;

&lt;h3 id=&quot;bufadd&quot;&gt;BufAdd&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;新增一个缓冲区至缓冲区列表&lt;/li&gt;
  &lt;li&gt;将一个 unlisted 缓冲区添加进 listed 缓冲区列表&lt;/li&gt;
  &lt;li&gt;修改 listed 缓冲区列表中某个缓冲区的名称&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;bufnew&quot;&gt;BufNew&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;新增一个缓冲区&lt;/li&gt;
  &lt;li&gt;修改缓冲区的名称&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;bufnewfile&quot;&gt;BufNewFile&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;当开始编辑一个不存在的文件时&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;测试示例&quot;&gt;测试示例&lt;/h2&gt;

通过一些实例来测试事件触发的时机，测试代码如下：

需要忽略掉 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*Cmd&lt;/code&gt; 事件，避免文件读写失败。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;spacevim.logger&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;logevent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;logevent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tbl_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endswith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Cmd&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getcompletion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Buf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;event&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;schedule_wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;执行命令：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:new&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ logevent ] [13:20:39:562] [ Debug ] BufNew5
[ logevent ] [13:20:39:562] [ Debug ] BufAdd5
[ logevent ] [13:20:39:562] [ Debug ] BufAdd5
[ logevent ] [13:20:39:562] [ Debug ] BufLeave4
[ logevent ] [13:20:39:562] [ Debug ] BufEnter5
[ logevent ] [13:20:39:562] [ Debug ] BufWinEnter5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;执行命令：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:enew&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ logevent ] [13:22:42:452] [ Debug ] BufNew6
[ logevent ] [13:22:42:452] [ Debug ] BufAdd6
[ logevent ] [13:22:42:452] [ Debug ] BufAdd6
[ logevent ] [13:22:42:452] [ Debug ] BufLeave4
[ logevent ] [13:22:42:452] [ Debug ] BufWinLeave4
[ logevent ] [13:22:42:452] [ Debug ] BufHidden4
[ logevent ] [13:22:42:452] [ Debug ] BufEnter6
[ logevent ] [13:22:42:452] [ Debug ] BufWinEnter6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;执行命令: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:echo bufadd(&apos;&apos;)&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ logevent ] [13:47:57:482] [ Debug ] BufNew6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo nvim_create_buf(v:false, v:true)&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ logevent ] [14:25:06:555] [ Debug ] BufNew5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo nvim_create_buf(v:true, v:true)&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ logevent ] [14:26:32:389] [ Debug ] BufNew11
[ logevent ] [14:26:32:389] [ Debug ] BufAdd11
[ logevent ] [14:26:32:389] [ Debug ] BufAdd11
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当打开一个文件后，执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set nobuflisted&lt;/code&gt;, 在执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set buflisted&lt;/code&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ logevent ] [14:38:15:888] [ Debug ] BufDelete4
[ logevent ] [14:38:19:857] [ Debug ] BufAdd4
[ logevent ] [14:38:19:857] [ Debug ] BufAdd4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

打开一个存在的文件：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:e README.md&lt;/code&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ logevent ] [14:44:15:717] [ Debug ] BufNew8
[ logevent ] [14:44:15:717] [ Debug ] BufAdd8
[ logevent ] [14:44:15:717] [ Debug ] BufAdd8
[ logevent ] [14:44:15:717] [ Debug ] BufLeave4
[ logevent ] [14:44:15:717] [ Debug ] BufWinLeave4
[ logevent ] [14:44:15:717] [ Debug ] BufHidden4
[ logevent ] [14:44:15:717] [ Debug ] BufReadPre8
[ logevent ] [14:44:15:717] [ Debug ] BufReadPost8
[ logevent ] [14:44:15:717] [ Debug ] BufReadPost8
[ logevent ] [14:44:15:717] [ Debug ] BufEnter8
[ logevent ] [14:44:15:717] [ Debug ] BufWinEnter8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

打开一个不存在的新文件: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:e newfile.txt&lt;/code&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ logevent ] [14:45:56:519] [ Debug ] BufNew10
[ logevent ] [14:45:56:519] [ Debug ] BufAdd10
[ logevent ] [14:45:56:519] [ Debug ] BufAdd10
[ logevent ] [14:45:56:519] [ Debug ] BufLeave4
[ logevent ] [14:45:56:519] [ Debug ] BufWinLeave4
[ logevent ] [14:45:56:519] [ Debug ] BufHidden4
[ logevent ] [14:45:56:519] [ Debug ] BufNewFile10
[ logevent ] [14:45:56:519] [ Debug ] BufEnter10
[ logevent ] [14:45:56:519] [ Debug ] BufWinEnter10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上述功能，做成了一个独立的 Neovim 插件：&lt;a href=&quot;https://github.com/wsdjeg/logevent.nvim&quot;&gt;wsdjeg/logevent.nvim&lt;/a&gt;

可以使用 &lt;a href=&quot;https://github.com/wsdjeg/nvim-plug&quot;&gt;nvim-plug&lt;/a&gt; 直接安装：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;plug&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/logevent.nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 07 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-buf-events/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-buf-events/</guid>
        
        <category>neovim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>(Neo)Vim 括号补全插件比较</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#实现逻辑及功能比较&quot; id=&quot;markdown-toc-实现逻辑及功能比较&quot;&gt;实现逻辑及功能比较&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#auto-pairs&quot; id=&quot;markdown-toc-auto-pairs&quot;&gt;auto-pairs&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#neopairsvim&quot; id=&quot;markdown-toc-neopairsvim&quot;&gt;neopairs.vim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#nvim-autopairs&quot; id=&quot;markdown-toc-nvim-autopairs&quot;&gt;nvim-autopairs&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#维护状态&quot; id=&quot;markdown-toc-维护状态&quot;&gt;维护状态&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

输入模式下，成对符号的自动补全一直是比较常用的功能。使用了很多年 &lt;a href=&quot;https://github.com/Raimondi/delimitMate&quot;&gt;delimitMate&lt;/a&gt; ，
基本功能正常，但是偶尔会出现卡屏现象，等一段时间或者按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctrl-c&lt;/code&gt; 可以结束卡屏，但是会输入很多个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Plug&amp;gt;delimitMate(&lt;/code&gt; 。
但是这一现象并无法百分百重现。

想着这么多年过去了，会不会有新的更好用的插件，于是搜了下，目前已知的括号补全插件有：

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Raimondi/delimitMate&quot;&gt;delimitMate&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Shougo/neopairs.vim&quot;&gt;neopairs.vim&lt;/a&gt;：需要 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exists(&apos;#CompleteDone&apos;) == 1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/windwp/nvim-autopairs&quot;&gt;nvim-autopairs&lt;/a&gt;：需要 Neovim 0.7.0+&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/echasnovski/mini.pairs&quot;&gt;mini.pairs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/jiangmiao/auto-pairs&quot;&gt;auto-pairs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/m4xshen/autoclose.nvim&quot;&gt;autoclose.nvim&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/altermo/ultimate-autopair.nvim&quot;&gt;ultimate-autopair.nvim&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;实现逻辑及功能比较&quot;&gt;实现逻辑及功能比较&lt;/h2&gt;

&lt;h3 id=&quot;auto-pairs&quot;&gt;auto-pairs&lt;/h3&gt;

仓库中 Vim 脚本只有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugin/auto-pairs.vim&lt;/code&gt; (673 行)。 监听 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BufEnter&lt;/code&gt; 事件，映射 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g:AutoPairs&lt;/code&gt; 所设定的成对符号。

&lt;h3 id=&quot;neopairsvim&quot;&gt;neopairs.vim&lt;/h3&gt;

通过监听 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CompleteDone&lt;/code&gt; 事件，判断补全 item 的结尾是否匹配设定的成对符号。

&lt;h3 id=&quot;nvim-autopairs&quot;&gt;nvim-autopairs&lt;/h3&gt;

是使用 Lua 实现的 Neovim 插件。在 &lt;a href=&quot;https://github.com/windwp/nvim-autopairs/blob/c15de7e7981f1111642e7e53799e1211d4606cb9/lua/nvim-autopairs.lua#L208&quot;&gt;nvim-autopairs.setup&lt;/a&gt; 函数里使用以下三组事件监听来实现补全。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_augroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;autopairs_buf&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BufEnter&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BufWinEnter&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;--- M.on_attach&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;BufDelete&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;FileType&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M.on_attach&lt;/code&gt; 函数里，主要有一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expr&lt;/code&gt; 映射及一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InsertCharPre&lt;/code&gt; 事件监听：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enable_insert_auto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- 初始化是否插入的 flag&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr_map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_buf_set_keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bufnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;i&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;--- 设定 expr 映射&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rule&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;-- 根据每个规则映射快捷键，并计算是 enable_insert_auto 值&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enable_insert_auto&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;InsertCharPre&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;--- 如果 enable_insert_auto 为 true， 则监听 InsertCharPre 事件&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;维护状态&quot;&gt;维护状态&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;repo&lt;/th&gt;
      &lt;th&gt;Github stars&lt;/th&gt;
      &lt;th&gt;Issues&lt;/th&gt;
      &lt;th&gt;pull requests&lt;/th&gt;
      &lt;th&gt;last commit&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;auto-pairs&lt;/td&gt;
      &lt;td&gt;4.1k&lt;/td&gt;
      &lt;td&gt;138 Open / 155 Closed&lt;/td&gt;
      &lt;td&gt;27 Open / 53 Closed&lt;/td&gt;
      &lt;td&gt;Feb 27, 2019&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;delimitMate&lt;/td&gt;
      &lt;td&gt;2k&lt;/td&gt;
      &lt;td&gt;47 Open / 219 Closed&lt;/td&gt;
      &lt;td&gt;5 Open / 36 Closed&lt;/td&gt;
      &lt;td&gt;Dec 14, 2020&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;nvim-autopairs&lt;/td&gt;
      &lt;td&gt;3k&lt;/td&gt;
      &lt;td&gt;12 Open / 287 Closed&lt;/td&gt;
      &lt;td&gt;1 Open / 157 Closed&lt;/td&gt;
      &lt;td&gt;May 20 2024&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;neopairs.vim&lt;/td&gt;
      &lt;td&gt;31&lt;/td&gt;
      &lt;td&gt;0 Open / 4 Closed&lt;/td&gt;
      &lt;td&gt;0 Open / 0 Closed&lt;/td&gt;
      &lt;td&gt;Mar 16, 2016&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

mini.pairs 仓库有2个：&lt;a href=&quot;https://github.com/echasnovski/mini.nvim&quot;&gt;mini.nvim&lt;/a&gt;、&lt;a href=&quot;https://github.com/echasnovski/mini.pairs&quot;&gt;mini.pairs&lt;/a&gt;。
因为 mini.nvim 仓库实际上是由几十个独立插件组合而成，其 Issues 跟 pull requests 列表应对到 mini.pairs 上到底有多少，无法评估。

auto-pairs 有一个较活跃的 fork 版本&lt;a href=&quot;https://github.com/LunarWatcher/auto-pairs&quot;&gt;LunarWatcher/auto-pairs&lt;/a&gt;，目前维护状态正常：

</description>
        <pubDate>Thu, 27 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/comparison-of-auto-pairs-plugins/</link>
        <guid isPermaLink="true">https://wsdjeg.net/comparison-of-auto-pairs-plugins/</guid>
        
        <category>vim</category>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Lua 与 Vim Script 之间函数相互调用</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#基本兼容逻辑&quot; id=&quot;markdown-toc-基本兼容逻辑&quot;&gt;基本兼容逻辑&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#vim-script-中调用-lua&quot; id=&quot;markdown-toc-vim-script-中调用-lua&quot;&gt;Vim Script 中调用 Lua&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#lua-中调用-vim-script-函数&quot; id=&quot;markdown-toc-lua-中调用-vim-script-函数&quot;&gt;Lua 中调用 Vim Script 函数&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

在使用 Neovim 之前，一直使用的是 Vim Script 写 Vim 脚本。随着 Neovim 的出现，以及 Lua 的速度优势，于是将之前写的插件使用 Lua 进行重写了。
在这里记录一些从 Vim Script 切换到 Lua 遇到的一些问题，以及前后兼容的写法。

&lt;h2 id=&quot;基本兼容逻辑&quot;&gt;基本兼容逻辑&lt;/h2&gt;

个人比较看重脚本的向后兼容，在非必要的情况下，对外的接口函数不会改变，通过以下一个示例大致展示了如何做到前后版本的脚本兼容。

比如，早期的 Vim Script 脚本实现的脚本如下：

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoload/test.vim&lt;/code&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; test#test&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  echo &lt;span class=&quot;s2&quot;&gt;&quot;hello &quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; name
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

那么，对于 Neovim 新版本的支持，可以使用 Lua 实现类似的功能：

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lua/test.lua&lt;/code&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;hello &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

为了让前面的 test.vim 使用 Lua 函数，可以做如下修改：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; test#test&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;lua&lt;/span&gt; require&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;test&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;test&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;api&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;nvim_eval&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    echo &lt;span class=&quot;s2&quot;&gt;&quot;hello &quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; name
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上函数存在一个问题，就是每次调用时，都会去检测一次版本，可以将脚本修改为：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; test#test&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;lua&lt;/span&gt; require&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;test&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;test&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;api&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;nvim_eval&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; test#test&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    echo &lt;span class=&quot;s2&quot;&gt;&quot;hello &quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; name
  &lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这样一来，版本检测仅仅在这个脚本文件被读取载入时才执行一次，在这之后 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test#test(name)&lt;/code&gt; 这个函数的本体仅限于一行代码。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;lua&lt;/span&gt; require&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;test&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;test&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;api&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;nvim_eval&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;vim-script-中调用-lua&quot;&gt;Vim Script 中调用 Lua&lt;/h2&gt;

上述的示例中只有一种调用方式，即使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:lua&lt;/code&gt; 命令，该命令使用有两种方式。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;lua&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;hello&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;lua&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; EOF
  &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;hello&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
EOF
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此外，使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:lua&lt;/code&gt; 命令，如果遇到 Vim Script 函数原先需要有返回值的话，比较麻烦，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;luaeval()&lt;/code&gt; 函数，比如：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; test#test&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;luaeval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;require(&apos;test&apos;).test(vim.api.nvim_eval(&apos;name&apos;))&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&quot; 也可以使用 return 返回值&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;luaeval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;require(&apos;test&apos;).test(vim.api.nvim_eval(&apos;name&apos;))&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

Neovim 0.5.0 增加了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v:lua&lt;/code&gt;，可以更加方便地在 Vim Script 中调用 Lua, 示例如下：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; test#test&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&quot; 这里可以直接使用参数，而不需要使用 nvim_eval&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lua&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;require&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;test&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;test&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;lua-中调用-vim-script-函数&quot;&gt;Lua 中调用 Vim Script 函数&lt;/h2&gt;

Neovim 提供了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.fn&lt;/code&gt; 以及 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim_call_function(fn, argv)&lt;/code&gt;。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- built-in functions&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;executable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- User autoload function&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;test#test&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

对于 Vim 的 funcref 变量，可以使用如下方式调用：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:test_hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:fn&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;s:test_hello&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; test#run&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;fn&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; fn &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;-3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; fn &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:fn&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lua&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;require&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;test&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;run&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;fn&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Tue, 11 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/call-function-between-lua-and-vim-script/</link>
        <guid isPermaLink="true">https://wsdjeg.net/call-function-between-lua-and-vim-script/</guid>
        
        <category>neovim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>更新 Neovim 遇到的问题</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#升级-neovim&quot; id=&quot;markdown-toc-升级-neovim&quot;&gt;升级 Neovim&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#不兼容的改动&quot; id=&quot;markdown-toc-不兼容的改动&quot;&gt;不兼容的改动&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#vimov_te-报错&quot; id=&quot;markdown-toc-vimov_te-报错&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.o.v_te&lt;/code&gt; 报错&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#窗口分割高亮-vertsplit-失效&quot; id=&quot;markdown-toc-窗口分割高亮-vertsplit-失效&quot;&gt;窗口分割高亮 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VertSplit&lt;/code&gt; 失效&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#treesitter-高亮报错&quot; id=&quot;markdown-toc-treesitter-高亮报错&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;treesitter&lt;/code&gt; 高亮报错&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#切回稳定版&quot; id=&quot;markdown-toc-切回稳定版&quot;&gt;切回稳定版&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

因为在维护 SpaceVim 这一项目，虽然我自己目前日常使用 neovim-0.9.5，但是还有不少用户会使用 neovim-nightly 版本。
因此，升级至每日构建版本测试 SpaceVim。

&lt;h2 id=&quot;升级-neovim&quot;&gt;升级 Neovim&lt;/h2&gt;

Windows 下升级也比较简单，使用 scoop 命令即可：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scoop uninstall neovim
scoop install neovim-nightly
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;不兼容的改动&quot;&gt;不兼容的改动&lt;/h2&gt;

安装后，启动一堆错误，也做了一部分修复，commits 如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;* 2ad0da42 - perf(treesitter): add default setup function (Eric Wong 49 minutes ago)
* f8b280e0 - fix(flygrep): remove `t_ve` option (Eric Wong 68 minutes ago)
* c46968d5 - fix(colorscheme): link WinSeparator to VertSplit (Eric Wong 79 minutes ago)
* 9ee8606e - fix(telescope): fix deoplete autocmd (Eric Wong 82 minutes ago)
* 74c93c6c - chore(treesitter): update nvim-treesitter to 0.9.1 for Nvim-0.8.x (Eric Wong 2 hours ago)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;vimov_te-报错&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.o.v_te&lt;/code&gt; 报错&lt;/h3&gt;

原先，在我的代码里有很多通过设置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;v_te&lt;/code&gt; 选项来实现修改光标的造型。但是升级到新版本后，就报如下错误：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Error detected while processing function SpaceVim#plugins#flygrep#open:
line    1:
E5108: Error executing lua C:\Users\wsdjeg\.SpaceVim\/lua/spacevim/plugin/flygrep.lua:780: Unknown option &apos;t_ve&apos;
stack traceback:
	[C]: in function &apos;__index&apos;
	C:\Users\wsdjeg\.SpaceVim\/lua/spacevim/plugin/flygrep.lua:780: in function &apos;open&apos;
	[string &quot;:lua&quot;]:1: in main chunk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

检查了下源码，原来是因为执行了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.o.v_te&lt;/code&gt;，尝试做了一些测试，增加&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exists()&lt;/code&gt;判断，可恨的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exists(&apos;&amp;amp;t_ve&apos;)&lt;/code&gt; 居然返回 1。
那么就无法判断了，只能是删除这些设置。

&lt;h3 id=&quot;窗口分割高亮-vertsplit-失效&quot;&gt;窗口分割高亮 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VertSplit&lt;/code&gt; 失效&lt;/h3&gt;

更新后，分割窗口的竖线没有高亮了。查了下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:hi VertSplit&lt;/code&gt;，输出结果显示高亮设置正常。看了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h hl-VertSplit&lt;/code&gt; 才知道，原来分割窗口的高亮组名称修改了。
修改成了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WinSeparator&lt;/code&gt;。因此在 ColorScheme 的 autocmd 内增加了：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;hi link WinSeparator VertSplit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;treesitter-高亮报错&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;treesitter&lt;/code&gt; 高亮报错&lt;/h3&gt;

这是我遇到最无语的错误。每当打开 lua 文件、help 文件 就会弹出报错 treesitter parser 不存在。起初我以为是 nvim-treesitter 的问题，更新并增加配置禁用所有的高亮都不行。

报错如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Error detected while processing function startify#open_buffers[13]..&amp;lt;SNR&amp;gt;276_open_buffer[12]..BufReadPost Autocommands for &quot;*&quot;:
Error executing lua callback: ...s\neovim-nightly\current\share\nvim\runtime\filetype.lua:30: Error executing lua: ...s\neovim-nightly\current\share\nvim\runtime\filetype.lua:31: function startify#open_buffers[13]..&amp;lt;SNR&amp;gt;276_open_buffer[12]..BufReadPost Autocommands for &quot;*&quot;..FileType Autocommands for &quot;*&quot;..function &amp;lt;SNR&amp;gt;1_LoadFTPlugin[20]..script D:\Scoop\apps\neovim-nightly\current\share\nvim\runtime\ftplugin\lua.lua: Vim(runtime):E5113: Error while calling lua chunk: ...rrent\share\nvim\runtime/lua/vim/treesitter/language.lua:104: no parser for &apos;lua&apos; language, see :help treesitter-parsers
stack traceback:
	[C]: in function &apos;error&apos;
	...rrent\share\nvim\runtime/lua/vim/treesitter/language.lua:104: in function &apos;add&apos;
	...t\share\nvim\runtime/lua/vim/treesitter/languagetree.lua:112: in function &apos;new&apos;
	...ightly\current\share\nvim\runtime/lua/vim/treesitter.lua:41: in function &apos;_create_parser&apos;
	...ightly\current\share\nvim\runtime/lua/vim/treesitter.lua:108: in function &apos;get_parser&apos;
	...ightly\current\share\nvim\runtime/lua/vim/treesitter.lua:416: in function &apos;start&apos;
	...ovim-nightly\current\share\nvim\runtime\ftplugin\lua.lua:2: in main chunk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:help treesitter-parsers&lt;/code&gt; 同样报错，理解为打开 help 文件也报错，同只执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h&lt;/code&gt;。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Error detected while processing modelines[274]..FileType Autocommands for &quot;*&quot;..function &amp;lt;SNR&amp;gt;1_LoadFTPlugin[20]..script D:\Scoop\apps\neovim-nightly\current\share\nvim\runtime\ftplugin\help.lua:
E5113: Error while calling lua chunk: ...rrent\share\nvim\runtime/lua/vim/treesitter/language.lua:104: no parser for &apos;vimdoc&apos; language, see :help treesitter-parsers
stack traceback:
	[C]: in function &apos;error&apos;
	...rrent\share\nvim\runtime/lua/vim/treesitter/language.lua:104: in function &apos;add&apos;
	...t\share\nvim\runtime/lua/vim/treesitter/languagetree.lua:112: in function &apos;new&apos;
	...ightly\current\share\nvim\runtime/lua/vim/treesitter.lua:41: in function &apos;_create_parser&apos;
	...ightly\current\share\nvim\runtime/lua/vim/treesitter.lua:108: in function &apos;get_parser&apos;
	...ightly\current\share\nvim\runtime/lua/vim/treesitter.lua:416: in function &apos;start&apos;
	...vim-nightly\current\share\nvim\runtime\ftplugin\help.lua:2: in main chunk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

于是，禁用 SpaceVim 的 treesitter 模块，任然报错。查看了 neovim-nightly 的源码，发现，原来在这几个文件里面默认增加了：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.treesitter.start()&lt;/code&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;D:\Scoop\apps\neovim-nightly\current\share\nvim\runtime\ftplugin\help.lua&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;D:/Scoop/apps/neovim-nightly/0.10.0-2559/share/nvim/runtime/ftplugin/lua.lua&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;等等，懒得去一个个搜了。&lt;/li&gt;
&lt;/ul&gt;

执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat D:/Scoop/apps/neovim-nightly/0.10.0-2559/share/nvim/runtime/ftplugin/lua.lua&lt;/code&gt;， 发现就两行代码，也没有任何条件判断跟 error handle。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-- use treesitter over syntax
vim.treesitter.start()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;切回稳定版&quot;&gt;切回稳定版&lt;/h2&gt;

说实话，没空去这样试错。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scoop uninstall neovim-nightly
scoop install neovim
nvim --version
NVIM v0.9.5
Build type: RelWithDebInfo
LuaJIT 2.1.1703942320
Compilation: C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe /MD /Zi /O2 /Ob1  -W3 -wd4311 -wd4146 -DUNIT_TESTING -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_WIN32_WINNT=0x0602 -DMSWIN -DINCLUDE_GENERATED_DECLARATIONS -ID:/a/neovim/neovim/.deps/usr/include/luajit-2.1 -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/build/src/nvim/auto -ID:/a/neovim/neovim/build/include -ID:/a/neovim/neovim/build/cmake.config -ID:/a/neovim/neovim/src -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include

   system vimrc file: &quot;$VIM\sysinit.vim&quot;
  fall-back for $VIM: &quot;C:/Program Files (x86)/nvim/share/nvim&quot;

Run :checkhealth for more info
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Mon, 11 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/fucking-problems-when-update-neovim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/fucking-problems-when-update-neovim/</guid>
        
        <category>neovim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>修复 git clone 问题: gnutls_handshake() failed</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#前因&quot; id=&quot;markdown-toc-前因&quot;&gt;前因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#尝试诊断&quot; id=&quot;markdown-toc-尝试诊断&quot;&gt;尝试诊断&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#重新编译&quot; id=&quot;markdown-toc-重新编译&quot;&gt;重新编译&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;前因&quot;&gt;前因&lt;/h2&gt;

今天在 wsl 内将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.SpaceVim&lt;/code&gt; 仓库的远程地址设置成 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://spacevim.org/git/repos/SpaceVim/&lt;/code&gt; 后，再执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull&lt;/code&gt; 出现错误：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fatal: unable to access &apos;https://spacevim.org/git/repos/SpaceVim/&apos;: gnutls_handshake() failed: Error in the pull function.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

但是，恢复成 github 或者 gitlab 仓库地址后，就又可以执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull&lt;/code&gt; 了。

&lt;h2 id=&quot;尝试诊断&quot;&gt;尝试诊断&lt;/h2&gt;

执行如下命令，看看网络链接到底怎么回事：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GIT_CURL_VERBOSE=1 git pull
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

输出为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;23:29:04.865626 http.c:664              == Info: Couldn&apos;t find host spacevim.org in the (nil) file; using defaults
23:29:04.884061 http.c:664              == Info:   Trying 104.21.53.107:443...
23:29:05.085433 http.c:664              == Info:   Trying 2606:4700:3037::ac43:d405:443...
23:29:05.085549 http.c:664              == Info: Immediate connect fail for 2606:4700:3037::ac43:d405: Network is unreachable
23:29:05.085601 http.c:664              == Info:   Trying 2606:4700:3032::6815:356b:443...
23:29:05.085623 http.c:664              == Info: Immediate connect fail for 2606:4700:3032::6815:356b: Network is unreachable
23:29:05.118268 http.c:664              == Info: Connected to spacevim.org (104.21.53.107) port 443 (#0)
23:29:05.138108 http.c:664              == Info: found 372 certificates in /etc/ssl/certs
23:29:05.138186 http.c:664              == Info: GnuTLS ciphers: NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509:-VERS-SSL3.0
23:29:05.138223 http.c:664              == Info: ALPN, offering h2
23:29:05.138240 http.c:664              == Info: ALPN, offering http/1.1
23:29:05.149601 http.c:664              == Info: gnutls_handshake() failed: Error in the pull function.
23:29:05.149680 http.c:664              == Info: Closing connection 0
fatal: unable to access &apos;https://spacevim.org/git/repos/SpaceVim/&apos;: gnutls_handshake() failed: Error in the pull function.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;重新编译&quot;&gt;重新编译&lt;/h2&gt;

删除已有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;:

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt uninstall git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

下载 git 源码

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget &quot;https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.9.5.tar.xz&quot;
tar -xvf git-2.9.5.tar.xz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

安装依赖

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt-get update
sudo apt-get install curl jq -y
sudo apt-get install build-essential autoconf dh-autoreconf -y
sudo apt-get install libcurl4-openssl-dev gettext -y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

编译

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make configure
./configure --prefix=/usr --with-openssl
make -j4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

安装

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo make install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Fri, 23 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/fix-git-clone-in-wsl/</link>
        <guid isPermaLink="true">https://wsdjeg.net/fix-git-clone-in-wsl/</guid>
        
        <category>git</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>《热辣滚烫》观后感</title>
        <description>最近刷视频总是刷到热辣滚烫的相关内容，趁着假日就来看看咯，确实挺不错：

&lt;style&gt;
  .image-gallery {
    overflow: auto;
    margin-left: -1% !important;
  }
  .image-gallery li {
    float: left;
    display: block;
    padding:3px 3px;
    width: 19%;
  }
  .image-gallery li a {
    text-align: center;
    text-decoration: none !important;
    color: #777;
  }
  .image-gallery li a span {
    display: block;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    padding: 3px 0;
  }
  .image-gallery li a img {
    width: 100%;
    display: block;
  }
&lt;/style&gt;

&lt;ul class=&quot;image-gallery&quot;&gt;
  
&lt;/ul&gt;

剧中杜乐莹总是毫无保留地对朋友真心付出，即便是知道对方有私心在，仍然坚持按照内心想法去做，确实难能可贵。

短短两小时的电影，看到主角为了自己的梦想所做出的改变，和所坚持的，有些汗颜，似乎我也快忘记了自己的梦想。
</description>
        <pubDate>Thu, 15 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/movie-review-YOLO/</link>
        <guid isPermaLink="true">https://wsdjeg.net/movie-review-YOLO/</guid>
        
        <category>movie</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>从 Github 迁移到 Gitlab</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#尝试-gitlab-的-page-功能&quot; id=&quot;markdown-toc-尝试-gitlab-的-page-功能&quot;&gt;尝试 Gitlab 的 page 功能&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#最终方案-cloudflare-page&quot; id=&quot;markdown-toc-最终方案-cloudflare-page&quot;&gt;最终方案 cloudflare page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

大概一周多之前，登录 Github 网页版时候总是提示要启用两步验证。
因为比较忙，也没太在意，就点了忽略。等到最近两天，直接是不让登录了，必须要启用两步验证才可以登录。
着急要处理事情，结果不让登录，手上也没有能进行两步验证的工具。

这样的体验让我感到非常的暴躁。
一向不喜欢受制于乱七八糟的规则，决定把项目和仓库转移出去。
对于我来说，GitHub 也好，Gitlab 也好，仅仅是一个存储版本控制仓库的地方，
实在难以理解这类平台总喜欢折腾出各种花俏功能做什么。

也正式这个原因，让我决定把仓库转移到 Gitlab，因为我还保留有原 Github 账号的 ssh 密钥。
因此可以在本地继续推送代码，于是清空了仓库，并备注了对应的 Gitlab 的仓库地址。

&lt;h2 id=&quot;尝试-gitlab-的-page-功能&quot;&gt;尝试 Gitlab 的 page 功能&lt;/h2&gt;

Gitlab 也提供了类似于 Github page 的功能，
只不过他的自定义域名管理非常让人不爽，
逻辑居然是重定向到项目的固定域名。于是，每次访问 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spacevim.org&lt;/code&gt; 时，都给我重定向到
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;https://spacevim-spacevim-c3011a6b21af70a6e8848d17c11652755bdad5d4e36c3.gitlab.io/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

经过多次尝试后，果断放弃了。

&lt;h2 id=&quot;最终方案-cloudflare-page&quot;&gt;最终方案 cloudflare page&lt;/h2&gt;

因为域名在 Cloudflare 上，并且该平台也提供了静态网站构建的功能，因此，没必要舍近求远，直接使用 cloudflare page，并且把本站及 SpaceVim 的官网也一并移过来。

在构建本站时候，一直遇到一个错误：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Liquid Exception: incompatible character encodings: ASCII-8BIT and UTF-8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

谷歌搜了一堆答案，要么是在 default.html 内增加 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;meta charset=&quot;utf-8&quot; /&amp;gt;&lt;/code&gt;, 要么是在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt; 里面增加 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;encoding: utf-8&lt;/code&gt;。尝试下来都不行。

感谢 vimzh 群友依云提供的答案，在构建时，增加环境变量：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export LANG=C.UTF-8&lt;/code&gt;

</description>
        <pubDate>Wed, 27 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/Migrate-from-GitHub-to-GitLab/</link>
        <guid isPermaLink="true">https://wsdjeg.net/Migrate-from-GitHub-to-GitLab/</guid>
        
        <category>gitlab</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>非常棒的安卓输入法 fcitx-android</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#初识-fcitx5-android&quot; id=&quot;markdown-toc-初识-fcitx5-android&quot;&gt;初识 fcitx5-android&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#fcitx5-android-特点&quot; id=&quot;markdown-toc-fcitx5-android-特点&quot;&gt;fcitx5-android 特点&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#隐私策略&quot; id=&quot;markdown-toc-隐私策略&quot;&gt;隐私策略&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#操作可配置性&quot; id=&quot;markdown-toc-操作可配置性&quot;&gt;操作可配置性&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#界面可配置性&quot; id=&quot;markdown-toc-界面可配置性&quot;&gt;界面可配置性&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

大概一个多月以前，我看到过这样一篇文字&lt;a href=&quot;https://felixc.at/2010/01/pinyin-input-method-user-experience-evaluation/&quot;&gt;《几款流行拼音输入法的“用户体验”评测(Win)》&lt;/a&gt;。
而我自己手机上一直使用的是华为版的百度输入法，虽然我不知道这个输入法到底会上传哪些内容，但是个人感觉还是不安全，因为打字输入涉及的东西太多。
聊天信息、密码等等，这些内容不应该存储在不可控的服务器上。

&lt;h2 id=&quot;初识-fcitx5-android&quot;&gt;初识 fcitx5-android&lt;/h2&gt;

于是，我找到了这样一款手机输入法 &lt;a href=&quot;https://github.com/fcitx5-android/fcitx5-android&quot;&gt;fcitx5-android&lt;/a&gt;。Fcitx 的旧全名是“Free Chinese Input Tool of X”的首字母缩写，相信大家并不陌生，它是 Linux 系统下面一款开源、免费的输入法框架。早期我在使用 Ubuntu/ArchLinux 时候都是使用的这款输入法。
非常开心有人将这一输入法移植到了安卓平台。

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fcitx5-android&lt;/code&gt; 的安装方式也比较简单，可以直接从 &lt;a href=&quot;https://f-droid.org/packages/org.fcitx.fcitx5.android/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F-Droid&lt;/code&gt; 网站&lt;/a&gt;直接下载 APK 安装包。切记，根据自己的手机选择对应的 CPU 架构，一般手机都是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arm64-v8a&lt;/code&gt;。

&lt;h2 id=&quot;fcitx5-android-特点&quot;&gt;fcitx5-android 特点&lt;/h2&gt;

目前 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fcitx5-android&lt;/code&gt; 只支持全键盘输入模式，恰巧我也是习惯于全键盘输入，因此使用倒是没有任何障碍。而我比较看重的功能特点主要包括：

&lt;h3 id=&quot;隐私策略&quot;&gt;隐私策略&lt;/h3&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fcitx5-android&lt;/code&gt; 不要求联网权限，也不收集任何个人信息。这一点是我切换该输入法的最核心原因，因为日常输入涉及的内容还是比较多的，因此对于哪些动辄上传收集输入信息的输入法还是比较反感的。

&lt;h3 id=&quot;操作可配置性&quot;&gt;操作可配置性&lt;/h3&gt;

一些键盘的操作习惯也是可以设置的。比如：

&lt;ul&gt;
  &lt;li&gt;输入标点、数字的方式&lt;/li&gt;
  &lt;li&gt;长按空格键行为&lt;/li&gt;
  &lt;li&gt;振动时长&lt;/li&gt;
  &lt;li&gt;默认展开工具栏，这点比较喜欢&lt;/li&gt;
  &lt;li&gt;长按延迟时间&lt;/li&gt;
&lt;/ul&gt;

更多功能就不一一罗列了，可以自行安装后打开配置界面查看。

&lt;h3 id=&quot;界面可配置性&quot;&gt;界面可配置性&lt;/h3&gt;

在主题设置界面，可以设置按键按下的水波纹特效，以及是否显示按键边框，甚至按键的横向边距、纵向边距、圆角半径都可以设置。
</description>
        <pubDate>Wed, 07 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/fcitx-android/</link>
        <guid isPermaLink="true">https://wsdjeg.net/fcitx-android/</guid>
        
        <category>fcitx</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Neo-tree.nvim 糟糕的体验</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#安装-neo-tree&quot; id=&quot;markdown-toc-安装-neo-tree&quot;&gt;安装 neo-tree&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#插件配置&quot; id=&quot;markdown-toc-插件配置&quot;&gt;插件配置&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#遇到的问题&quot; id=&quot;markdown-toc-遇到的问题&quot;&gt;遇到的问题&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#插件优势&quot; id=&quot;markdown-toc-插件优势&quot;&gt;插件优势&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

文件树插件也是我日常非常常用的插件之一。先前&lt;a href=&quot;../first-experience-with-nvim-tree/&quot;&gt;尝试过 nvim-tree&lt;/a&gt;，今天晚上花了一晚上时间测试了下 Neo-tree.nvim，测试版本为：&lt;a href=&quot;https://github.com/nvim-neo-tree/neo-tree.nvim/tree/e3b4ef0fc05b0c99526ffb941abe23ef4fdc8e4e&quot;&gt;Neo-tree.nvim@e3b4ef0&lt;/a&gt;。
总的来说体验不是很好。

&lt;strong&gt;测试环境：&lt;/strong&gt;

&lt;ul&gt;
  &lt;li&gt;操作系统：Window 11&lt;/li&gt;
  &lt;li&gt;Neovim 版本：NVIM 0.9.1&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;安装-neo-tree&quot;&gt;安装 neo-tree&lt;/h2&gt;

我的插件系统比较简单，直接下载 &lt;a href=&quot;https://github.com/nvim-neo-tree/neo-tree.nvim/archive/e3b4ef0fc05b0c99526ffb941abe23ef4fdc8e4e.zip&quot;&gt;neo-tree.zip&lt;/a&gt; 至 bundle 文件夹，并手动更新 RTP。

&lt;h2 id=&quot;插件配置&quot;&gt;插件配置&lt;/h2&gt;

参考 readme 上的介绍，直接完整复制默认配置，修改几个重要的配置，比如宽度、位置、自动关闭窗口等待。

&lt;h2 id=&quot;遇到的问题&quot;&gt;遇到的问题&lt;/h2&gt;

1、设置 Neo-tree 的初始化路径失败；

我给 SpaceVim 增加了这个插件的支持，目前有一个快捷键&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPC b t&lt;/code&gt;无法实现。按照文档所说&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Neotree dir=%:p:h&lt;/code&gt;无效，打开后根目录任然是当前目录。

2、设置快捷键不是很方便；

在配置文件里，action 都是一些预设值的 string。

3、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPC f o&lt;/code&gt; 快捷键每次弹窗需要确认是否切换目录。

我是经常会同时编辑不同的 git 仓库文件，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPC f o&lt;/code&gt; 设置为打开文件树并定位到当前文件位置，即为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Neotree reveal&lt;/code&gt;，但是每次一旦切换不同项目时都会弹窗提示：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;File is not in cmd， change to xxxxx
y/n
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

而且使用的是 insert 模式，我需要按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&amp;lt;Cr&amp;gt;&lt;/code&gt; 两下按键，应该提供一个设置选项，自动切换目录而不需要用户手动确认。并且，就算确认，完全可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getchar()&lt;/code&gt; 函数。

&lt;h2 id=&quot;插件优势&quot;&gt;插件优势&lt;/h2&gt;

当然了，这个插件也不是完全没有优势，个人感觉优势在：

1、支持多种 source，比如 buffers、git status 等，后续如果有机会，看看是否支持自定义。

2、git 状态的更新，使用的是异步函数，这点比 defx-git 要好一些，后者是我目前使用 defx 的一个痛点。

最后，暂时还是切换回 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;defx&lt;/code&gt;，期待 neo-tree 新的改进，后续有机会再尝试。
</description>
        <pubDate>Wed, 31 May 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/bad-experience-about-neotree/</link>
        <guid isPermaLink="true">https://wsdjeg.net/bad-experience-about-neotree/</guid>
        
        <category>neovim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>我的 Neovim 之旅</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#初始-neovim&quot; id=&quot;markdown-toc-初始-neovim&quot;&gt;初始 Neovim&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#neovim-异步-job-特性&quot; id=&quot;markdown-toc-neovim-异步-job-特性&quot;&gt;Neovim 异步 job 特性&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#neovim-定时器&quot; id=&quot;markdown-toc-neovim-定时器&quot;&gt;Neovim 定时器&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#悬浮窗口支持&quot; id=&quot;markdown-toc-悬浮窗口支持&quot;&gt;悬浮窗口支持&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#neovim-内置终端的使用&quot; id=&quot;markdown-toc-neovim-内置终端的使用&quot;&gt;Neovim 内置终端的使用&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;初始-neovim&quot;&gt;初始 Neovim&lt;/h2&gt;

在接触 Neovim 之前，我的主力编辑器一直是 Vim。在 Vim 增加 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+job&lt;/code&gt; 特性之前，
Vim 的所有函数都是在主线程内完成的，当执行某个需要很长时间的操作时，Vim 会卡住等待上一个操作完成。
这样的体验是非常不符合个人习惯的。因此，Geoff Greer 给 Vim 提交过&lt;a href=&quot;https://groups.google.com/g/vim_dev/c/-4pqDJfHCsM/m/LkYNCpZjQ70J&quot;&gt;异步执行的补丁&lt;/a&gt;，源码可以查阅&lt;a href=&quot;https://github.com/Floobits/vim&quot;&gt;Floobits/vim&lt;/a&gt;。同时，Thiago Padilha 也给 Vim 提交过类似的&lt;a href=&quot;https://groups.google.com/g/vim_dev/c/QF7Bzh1YABU/m/02-YGr7_sCwJ&quot;&gt;补丁&lt;/a&gt;，但是都因各种原因被拒绝，其实这也是我不太喜欢的一个 Vim 开发的弊端。

后来，Thiago Padilha 发起了 &lt;a href=&quot;https://github.com/neovim/neovim&quot;&gt;Neovim&lt;/a&gt; 项目，做了如下改进：

&lt;ol&gt;
  &lt;li&gt;增加异步 job 特性&lt;/li&gt;
  &lt;li&gt;悬浮窗口支持&lt;/li&gt;
  &lt;li&gt;增加 timer 支持&lt;/li&gt;
  &lt;li&gt;增加终端真色支持&lt;/li&gt;
  &lt;li&gt;增加 RPC 通讯支持&lt;/li&gt;
  &lt;li&gt;增加内置终端模拟器&lt;/li&gt;
&lt;/ol&gt;

虽然，以上的一些功能 Vim 后续也增加了，但是部分功能却是用了另外一种完全不兼容的方式。

&lt;h2 id=&quot;neovim-异步-job-特性&quot;&gt;Neovim 异步 job 特性&lt;/h2&gt;

Neovim 的异步 job 特性主要是提供了一个异步执行外部命令的函数。并且通过回调函数来响应输出的结果。比如：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;call jobstart([&apos;echo&apos;])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;neovim-定时器&quot;&gt;Neovim 定时器&lt;/h2&gt;

Neovim 增加了一个定时器功能，主要涉及函数为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;timer_start()&lt;/code&gt;，其函数原型为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;timer_start({time}, {callback} [, {options}])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;悬浮窗口支持&quot;&gt;悬浮窗口支持&lt;/h2&gt;

以往 Vim 支持垂直、水平分屏，而分屏时窗口的布局、屏幕内容都会发生改变。悬浮窗口提供了一种在不改变当前窗口布局的前提下，打开额外的窗口以展示新的内容。

Neovim 和 Vim 的分屏又是完全不一样的函数。因此我写了一个函数，来统一调用 Neovim 或者 Vim 的悬浮窗口。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:FLOAT&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; SpaceVim#api#&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;neovim#floating&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:FLOAT&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; SpaceVim#api#&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;vim#floating&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:FLOAT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;open_win&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bufnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;%&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;true&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;  \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;  \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;relative&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;editor&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;  \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;width&apos;&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;  \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;height&apos;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;lines&lt;/span&gt; * &lt;span class=&quot;m&quot;&gt;30&lt;/span&gt; / &lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;  \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;row&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;  \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;col&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;amp;&lt;span class=&quot;nb&quot;&gt;lines&lt;/span&gt; * &lt;span class=&quot;m&quot;&gt;30&lt;/span&gt; / &lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;  \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;neovim-内置终端的使用&quot;&gt;Neovim 内置终端的使用&lt;/h2&gt;

可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:terminal&lt;/code&gt; 命令打开内置终端。在终端窗口内，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-\ Ctrl-n&lt;/code&gt; 切换到 Normal 模式。

目前，内置的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:terminal&lt;/code&gt;命令不支持分屏模式，可以借助&lt;a href=&quot;https://github.com/vimlab/split-term.vim&quot;&gt;split-term.vim&lt;/a&gt;插件。
该插件增加了如下的使用方式：

&lt;ol&gt;
  &lt;li&gt;水平/垂直分屏打开终端&lt;/li&gt;
  &lt;li&gt;指定分屏终端窗口初始化大小&lt;/li&gt;
  &lt;li&gt;在新的标签页打开终端&lt;/li&gt;
&lt;/ol&gt;

优化内置终端的插件有很多种：

&lt;ul&gt;
  &lt;li&gt;https://github.com/voldikss/vim-floaterm&lt;/li&gt;
  &lt;li&gt;https://github.com/numToStr/FTerm.nvim&lt;/li&gt;
&lt;/ul&gt;

虽然这些插件都挺不错的，但是个人感觉没有必要那么复杂。目前，就个人而言，我仅仅使用了 Neovim 的悬浮窗口配合 termopen 函数。

&lt;blockquote&gt;
  &lt;a href=&quot;https://github.com/SpaceVim/SpaceVim/blob/763045513d6227a59bdb2a3a772740c3be97ac01/autoload/SpaceVim/layers/shell.vim#L153-L292&quot;&gt;shell.vim#L153-L292&lt;/a&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:SYSTEM&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; SpaceVim#api#&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;system&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:FLOAT&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; SpaceVim#api#&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;neovim#floating&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:WIN&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; SpaceVim#api#&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;vim#window&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:open_default_shell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;open_with_file_cwd&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; abort
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:open_with_file_cwd&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getwinvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;winnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;amp;buftype&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;terminal&apos;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getbufvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;winbufnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;winnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;_spacevim_shell_cwd&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; SpaceVim#plugins#projectmanager#current_root&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;%:p:h&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; SpaceVim#plugins#projectmanager#current_root&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;&quot; if the current file is not in a project, the projectmanager return empty&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;&quot; string. Then use current directory as default cwd.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getcwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;

  &lt;span class=&quot;c&quot;&gt;&quot; look for already opened terminal windows&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; windows &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;windo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;windows&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;winnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; windows
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getwinvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;amp;buftype&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;terminal&apos;&lt;/span&gt;
      exe &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;  &lt;span class=&quot;s1&quot;&gt;&apos;wincmd w&apos;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getbufvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;winbufnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;_spacevim_shell_cwd&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;k&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; startinsert do not work in gvim&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;startinsert&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
          normal&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; the opened terminal window is not the one we want.&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; close it, we&apos;re gonna open a new terminal window with the given l:path&lt;/span&gt;
        exe &lt;span class=&quot;s1&quot;&gt;&apos;wincmd c&apos;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:default_position&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;float&apos;&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;nb&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;*nvim_open_win&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:term_win_id&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;s:FLOAT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;open_win&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bufnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;%&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;true&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;          \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;            \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;relative&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;editor&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;            \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;width&apos;&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;            \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;height&apos;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;lines&lt;/span&gt; * &lt;span class=&quot;nv&quot;&gt;s:default_height&lt;/span&gt; / &lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;            \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;row&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;            \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;col&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;amp;&lt;span class=&quot;nb&quot;&gt;lines&lt;/span&gt; * &lt;span class=&quot;nv&quot;&gt;s:default_height&lt;/span&gt; / &lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;            \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

    exe &lt;span class=&quot;nb&quot;&gt;win_id2win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s:term_win_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;  &lt;span class=&quot;s1&quot;&gt;&apos;wincmd w&apos;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;&quot; no terminal window found. Open a new window&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; cmd &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:default_position&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;float&apos;&lt;/span&gt; ?
&lt;span class=&quot;se&quot;&gt;          \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;topleft split&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;          \&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:default_position&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;top&apos;&lt;/span&gt; ?
&lt;span class=&quot;se&quot;&gt;          \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;topleft split&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;          \&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:default_position&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;bottom&apos;&lt;/span&gt; ?
&lt;span class=&quot;se&quot;&gt;          \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;botright split&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;          \&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:default_position&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;right&apos;&lt;/span&gt; ?
&lt;span class=&quot;se&quot;&gt;          \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;rightbelow vsplit&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;leftabove vsplit&apos;&lt;/span&gt;
    exe cmd
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;lines&lt;/span&gt; * &lt;span class=&quot;nv&quot;&gt;s:default_height&lt;/span&gt; / &lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;winheight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s:default_position&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;top&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:default_position&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;bottom&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      exe &lt;span class=&quot;s1&quot;&gt;&apos;resize &apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;lines&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;shell_layer_win &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; open_terminal &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:open_terminals_buffers&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bufexists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;open_terminal&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getbufvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;open_terminal&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;_spacevim_shell_cwd&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;k&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt;
        exe &lt;span class=&quot;s1&quot;&gt;&apos;silent b&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; open_terminal
        &lt;span class=&quot;c&quot;&gt;&quot; clear the message&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;startinsert&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
          normal&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;c&quot;&gt;&quot; remove closed buffer from list&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s:open_terminals_buffers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;

  &lt;span class=&quot;c&quot;&gt;&quot; no terminal window with l:path as cwd has been found, let&apos;s open one&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:default_shell&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;terminal&apos;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;:terminal&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:SYSTEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;isWindows
          &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;shell&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;$SHELL&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; ? &lt;span class=&quot;s1&quot;&gt;&apos;cmd.exe&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; $SHELL
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;shell&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;$SHELL&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; ? &lt;span class=&quot;s1&quot;&gt;&apos;bash&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; $SHELL
        &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;enew&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; termopen&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;shell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;cwd&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; @bug cursor is not cleared when open terminal windows.&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; in neovim-qt when using :terminal to open a shell windows, the orgin&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; cursor position will be highlighted. switch to normal mode and back&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; is to clear the highlight.&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; This seem a bug of neovim-qt in windows.&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; cc @equalsraf&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:SYSTEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;isWindows &amp;amp;&amp;amp; &lt;span class=&quot;nb&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;nvim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;stopinsert&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;startinsert&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:term_buf_nr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bufnr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;%&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s:shell_cached_br&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;getcwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:term_buf_nr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; handle vim terminal&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:SYSTEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;isWindows
          &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;shell&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;$SHELL&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; ? &lt;span class=&quot;s1&quot;&gt;&apos;cmd.exe&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; $SHELL
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;shell&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;$SHELL&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; ? &lt;span class=&quot;s1&quot;&gt;&apos;bash&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; $SHELL
        &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:term_buf_nr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;term_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;shell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;cwd&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;curwin&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;term_finish&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;close&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s:open_terminals_buffers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:term_buf_nr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:_spacevim_shell&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;shell&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:_spacevim_shell_cwd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;path&lt;/span&gt;

      &lt;span class=&quot;c&quot;&gt;&quot; use WinEnter autocmd to update statusline&lt;/span&gt;
      doautocmd &lt;span class=&quot;nb&quot;&gt;WinEnter&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;setlocal&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nobuflisted&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nonumber&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;norelativenumber&lt;/span&gt;

      &lt;span class=&quot;c&quot;&gt;&quot; use q to hide terminal buffer in vim, if vimcompatible mode is not&lt;/span&gt;
      &lt;span class=&quot;c&quot;&gt;&quot; enabled, and smart quit is on.&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;g:spacevim_windows_smartclose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &amp;amp;&amp;amp; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;g:spacevim_vimcompatible&lt;/span&gt;
        exe &lt;span class=&quot;s1&quot;&gt;&apos;nnoremap &amp;lt;buffer&amp;gt;&amp;lt;silent&amp;gt; &apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:spacevim_windows_smartclose&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos; :hide&amp;lt;CR&amp;gt;&apos;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;startinsert&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      echo &lt;span class=&quot;s1&quot;&gt;&apos;:terminal is not supported in this version&apos;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:default_shell&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;# &lt;span class=&quot;s1&quot;&gt;&apos;VimShell&apos;&lt;/span&gt;
    VimShell
    imap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;esc&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;Plug&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;vimshell_enter&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Wed, 24 May 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/neovim-journey/</link>
        <guid isPermaLink="true">https://wsdjeg.net/neovim-journey/</guid>
        
        <category>neovim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>写给自己·关于健康</title>
        <description>上周，听到一则让我很吃惊的消息。&lt;a href=&quot;https://github.com/haoel&quot;&gt;陈浩（左耳朵耗子）&lt;/a&gt;因突发心梗辞世，享年只有四十七岁。
正常情况下，四十多岁正是事业、家庭黄金时间。当财富、声望都积累足够的时候，却没有时间去享受自己奋斗的果实，确实让人觉得惋惜。

其实，对于左耳朵耗子了解的并不多，甚至可以说完全不了解。这几天，不管是朋友圈，还是推特，抑或是订阅的一些博客，都在发文纪念他。
也正是读了这些文字才有了一些了解。其实，这类事情之前已经遇到过好几次了。比如：&lt;a href=&quot;https://github.com/RubyLouvre&quot;&gt;司徒正美&lt;/a&gt;。

想来，真的是健康是一，财富、声望、家庭等等一切都是零。

也正是因此，最近才开始关注一些生活习惯方面的资料。包括不限于：

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/zijie0/HumanSystemOptimization&quot;&gt;健康学习到150岁 - 人体系统调优不完全指南 &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;饮食&quot;&gt;饮食&lt;/h2&gt;

1、早餐：以往有时候因为熬夜，第二天早上起来的较晚，会错过酒店的早餐时间。又或者是因为早上赶时间，早餐只是应付式地吃一点，甚至是来不及吃。

&lt;blockquote&gt;
  给自己定一个闹铃，每天早餐预留充足时间
&lt;/blockquote&gt;

2、&lt;del&gt;夜宵&lt;/del&gt;：拒绝夜宵，晚上9点后，不再进食

&lt;h2 id=&quot;睡眠&quot;&gt;睡眠&lt;/h2&gt;

睡眠时间一直是一个大问题，应该是自15年之后，每天睡觉几乎都是11点半到12点半甚至1点。

想控制到10点之前，似乎是不现实的，后面尽量控制在11点-7点半，保证至少8小时睡眠。

&lt;h2 id=&quot;运动&quot;&gt;运动&lt;/h2&gt;

貌似没有什么适合自己的运动了。以前偶尔还去爬山，上次去宜兴竹海，只到半山腰就下来了。
</description>
        <pubDate>Mon, 22 May 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/20230522/</link>
        <guid isPermaLink="true">https://wsdjeg.net/20230522/</guid>
        
        <category>lifestyle</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>停用 v2ex 账号</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#贴子和回复无法删除&quot; id=&quot;markdown-toc-贴子和回复无法删除&quot;&gt;贴子和回复无法删除&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#未经允许公布用户邮箱和手机号&quot; id=&quot;markdown-toc-未经允许公布用户邮箱和手机号&quot;&gt;未经允许公布用户邮箱和手机号&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#以往发的文字无法修改&quot; id=&quot;markdown-toc-以往发的文字无法修改&quot;&gt;以往发的文字无法修改&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#随意移贴&quot; id=&quot;markdown-toc-随意移贴&quot;&gt;“随意”移贴&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#随意删号&quot; id=&quot;markdown-toc-随意删号&quot;&gt;随意删号&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#霸道降权&quot; id=&quot;markdown-toc-霸道降权&quot;&gt;霸道降权&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#针对-v2exfaq-上的回复&quot; id=&quot;markdown-toc-针对-v2exfaq-上的回复&quot;&gt;针对 v2ex/faq 上的回复&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#如何删除v2ex账号&quot; id=&quot;markdown-toc-如何删除v2ex账号&quot;&gt;如何删除V2EX账号&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

2016 年第一次接触 v2ex 的时候，觉得这个论坛做的还是非常不错的，相比老式的 BBS 论坛界面要舒服多了。于是，注册了一个账号：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;https://www.v2ex.com/member/wsdjeg V2EX 第 167678 号会员，加入于 2016-04-11 13:08:11 +08:00
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

随着使用时间的增加，慢慢发现也许 V2EX 这样的“&lt;strong&gt;个人网站&lt;/strong&gt;”并不适合我。罗列了一些存在的问题，以及个人的一些看法。

&lt;h2 id=&quot;贴子和回复无法删除&quot;&gt;贴子和回复无法删除&lt;/h2&gt;

这就存在一个文字版权问题了，自己发的贴子，都无权决定他的删除与否，简直可笑。

&lt;h2 id=&quot;未经允许公布用户邮箱和手机号&quot;&gt;未经允许公布用户邮箱和手机号&lt;/h2&gt;

再次说明了这个网站实际上就是一个个人维护、开放注册的个人网站，而且站长肆意妄为。

&lt;a href=&quot;https://quzheng.baidu.com/s/z2umua&quot;&gt;来自百度取证的证据分享&lt;/a&gt;

&lt;img src=&quot;../images/v2ex-privacy-leak.png&quot; alt=&quot;v2ex privacy leak&quot; /&gt;

&lt;h2 id=&quot;以往发的文字无法修改&quot;&gt;以往发的文字无法修改&lt;/h2&gt;

个人认为，人的认知和观点是会随着时间的推移、知识的积累、以及所经历的事情发生改变的。
所以偶尔回头去翻看自己写下的文字，还是希望有一个更新、修改的功能。当然，可以使用类似于 Git 仓库一样，保留修改记录。

&lt;h2 id=&quot;随意移贴&quot;&gt;“随意”移贴&lt;/h2&gt;

这里，我把“随意”加上了引号是因为可能有些人会认为这不是随意移贴，而是基于“某些规则”，
但是希望这个规则可以公开，并且接受大众修改意见。
否则，这给人的感觉 v2ex 就是一个站长私人的网站，只不过给了注册用户部分的编辑权限。

比如：当你发了一个帖子，讨论正火热的时候，管理员可以将帖子移至“水生火热”(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://www.v2ex.com/go/flamewar&lt;/code&gt;)标签下，
这个标签下的内容，非登录用户似乎是无法查阅的，会自动跳转至首页。

&lt;h2 id=&quot;随意删号&quot;&gt;随意删号&lt;/h2&gt;

可以看看这篇文章&lt;a href=&quot;https://yanyunfeng.com/article/73&quot;&gt;因用 AI 生成的内容回复帖子，V2EX 账号直接被封&lt;/a&gt;。
且不说这个规则是否合理，对于十年的老用户，而且是活跃的老用户，你（@Livid ）他妈的说删就删，谁敢再这个网站上写东西？

&lt;h2 id=&quot;霸道降权&quot;&gt;霸道降权&lt;/h2&gt;

社交类的平台，想必大家也不陌生。我自己以往就使用过QQ空间、人人网、朋友圈等等。这些平台有一个特点，你的好友、你所关注的人，他们的更新，会严格按照时间线展示给你。

但是 v2ex 这种降权就会很霸道，他会让你的更新出现在2天前、3天前、甚至更久之前的时间线上。结果就不言而喻了，其他人可能不会那么容易看到你所写的内容。

还有一些其他原因，后面想到再更新上来。

&lt;h2 id=&quot;针对-v2exfaq-上的回复&quot;&gt;针对 v2ex/faq 上的回复&lt;/h2&gt;

v2ex/faq 页面可能会修改，这里保留了 2024 年 8 月的内容：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;我是否可以编辑或者移动自己的主题？

在主题发布之后的 300 秒内，你可以自由地编辑自己的主题，或者将其移动到其他节点。但是在 300 秒（5 分钟）之后，
就不可以再进行这些操作了。对于编辑的限制是为了让大家对发表在 V2EX 的言论更加负责。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

简直是荒谬的理论，把完全不相干的两个事情强行联系起来。

&lt;h2 id=&quot;如何删除v2ex账号&quot;&gt;如何删除V2EX账号&lt;/h2&gt;

基于这些原因，即日起停用 v2ex 账号，写到这才发现，原来 v2ex 的账号，还不提供删除功能，这也太牛氓了。

v2ex 贴子(https://v2ex.com/t/1063942)链接已被移至水生火热，非登录用户无法访问，内容如下：

&lt;img src=&quot;https://img.spacevim.org/how-to-delete-v2ex-account.jpg&quot; alt=&quot;how-to-delete-v2ex-account&quot; /&gt;

使用谷歌搜索“&lt;a href=&quot;https://www.google.com/search?client=firefox-b-d&amp;amp;q=%E5%A6%82%E4%BD%95%E5%88%A0%E9%99%A4V2EX&quot;&gt;如何删除V2EX账号&lt;/a&gt;”可以看到不少人遇到类似的问题。
</description>
        <pubDate>Mon, 15 May 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/delete-v2ex-account/</link>
        <guid isPermaLink="true">https://wsdjeg.net/delete-v2ex-account/</guid>
        
        <category>lifestyle</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>母亲节·常回家看看</title>
        <description>五一期间没有来得及回家，这次周末正好是母亲节。周五晚上工作结束后，回了一趟老家，已经快半年没有回去了。

周六早上，带爷爷、奶奶、妈妈一起去扬州世博园玩玩。避开五一假期，也是另外一番景色。

&lt;style&gt;
  .image-gallery {
    overflow: auto;
    margin-left: -1% !important;
  }
  .image-gallery li {
    float: left;
    display: block;
    padding:3px 3px;
    width: 19%;
  }
  .image-gallery li a {
    text-align: center;
    text-decoration: none !important;
    color: #777;
  }
  .image-gallery li a span {
    display: block;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    padding: 3px 0;
  }
  .image-gallery li a img {
    width: 100%;
    display: block;
    box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
  }
&lt;/style&gt;

&lt;ul class=&quot;image-gallery&quot;&gt;
  
&lt;/ul&gt;

中午在宝能广场吃的“老土灶民间菜”，感觉他们家菜的口味还是挺不错的，而且也比较实惠。

吃完饭回家回家后陪爷爷奶奶还有妈妈打麻将，老年人爱好挺简单的。我记得我上次打牌还是去年11月份，手生的很。

礼拜天，是母亲节，今天中午选的是无锡融创茂的泰妃餐厅。
</description>
        <pubDate>Sun, 14 May 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/20230514/</link>
        <guid isPermaLink="true">https://wsdjeg.net/20230514/</guid>
        
        <category>life</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>介绍我的新插件 gfr.vim</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#为什么要开发-gfrvim&quot; id=&quot;markdown-toc-为什么要开发-gfrvim&quot;&gt;为什么要开发 gfr.vim&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#gfrvim-的功能特点&quot; id=&quot;markdown-toc-gfrvim-的功能特点&quot;&gt;gfr.vim 的功能特点&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#异步执行&quot; id=&quot;markdown-toc-异步执行&quot;&gt;异步执行&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#兼容-vimneovim&quot; id=&quot;markdown-toc-兼容-vimneovim&quot;&gt;兼容 Vim/Neovim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#弹窗消息界面&quot; id=&quot;markdown-toc-弹窗消息界面&quot;&gt;弹窗消息界面&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#如何安装&quot; id=&quot;markdown-toc-如何安装&quot;&gt;如何安装&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#如何使用&quot; id=&quot;markdown-toc-如何使用&quot;&gt;如何使用&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#后续计划&quot; id=&quot;markdown-toc-后续计划&quot;&gt;后续计划&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

今天向大家分享一个我刚写的 Vim 插件 &lt;a href=&quot;https://github.com/wsdjeg/gfr.vim&quot;&gt;gfr.vim&lt;/a&gt;。名字取自三个词语缩写：&lt;strong&gt;G&lt;/strong&gt;rep, &lt;strong&gt;F&lt;/strong&gt;ilter, &lt;strong&gt;R&lt;/strong&gt;eplace。顾名思义，这个插件提供的功能包括文本搜索、结果筛选以及文本替换功能。

&lt;h2 id=&quot;为什么要开发-gfrvim&quot;&gt;为什么要开发 gfr.vim&lt;/h2&gt;

Vim 文本搜索的插件已经非常多了，我自己也使用过很多种插件。比如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ack.vim&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ag.vim&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grepper.vim&lt;/code&gt; 等等。这些插件都提供了类似的功能，即为搜索制定的文字，并将结果输出到 Vim 的 quickfix window。
甚至，我之前还制作过一款实时异步搜索，并展示搜索结果的插件 flygrep.vim。

但是以上这些插件仅仅支持搜索指定文本的结果，不具备二次检索和替换的功能。

&lt;h2 id=&quot;gfrvim-的功能特点&quot;&gt;gfr.vim 的功能特点&lt;/h2&gt;

&lt;h3 id=&quot;异步执行&quot;&gt;异步执行&lt;/h3&gt;

这个插件中，我比较常用的命令是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Grep&lt;/code&gt;。实际上，Vim 本身也有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:grep&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:vimgrep&lt;/code&gt; 命令，功能是相同的，都是执行搜索命令，并且把搜索的结果展示在 quickfix 窗口内。
但是 Vim 自带的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:grep&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:vimgrep&lt;/code&gt; 命令是单线程的，如果搜索的文件夹内内容非常多会卡住当前 Vim 的操作界面，体验不是很好。

&lt;h3 id=&quot;兼容-vimneovim&quot;&gt;兼容 Vim/Neovim&lt;/h3&gt;

Vim 和 Neovim 的一些内置函数还是有些差异的，而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gfr.vim&lt;/code&gt; 集成了 SpaceVim 的 API，可以同时兼容 Vim 和 Neovim。

&lt;h3 id=&quot;弹窗消息界面&quot;&gt;弹窗消息界面&lt;/h3&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gfr.vim&lt;/code&gt; 使用了 SpaceVim 的 notify API，对于一些插件通知消息，在 Vim 右上方使用浮窗提示。

&lt;h2 id=&quot;如何安装&quot;&gt;如何安装&lt;/h2&gt;

和其他常用插件一样，你可以使用任意一个插件管理器来安装，比如使用 plug.vim：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Plug &apos;wsdjeg/gfr.vim&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在插件列表添加上面这段即可，启动 Vim 后执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:PlugInstall&lt;/code&gt;。

&lt;h2 id=&quot;如何使用&quot;&gt;如何使用&lt;/h2&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gfr.vim&lt;/code&gt; 提供了如下命令：

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Grep&lt;/code&gt;: 搜索指定的文本，该命令后面的参数即为需要搜索的文本，比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Grep hello&lt;/code&gt; 指的就是搜索 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt;。如果直接调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Grep&lt;/code&gt;，并且不带任何参数，那么会弹出一个输入框，可供输入需要搜索的文本。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Filter&lt;/code&gt;：检索上一次搜索的结果，可以理解为二次筛选。对于上一次搜索或者检索的结果，进行再一次的筛选。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:GrepSave&lt;/code&gt;：将当前的搜索结果保存至命名标签，以便于快速访问。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:GrepResum&lt;/code&gt;：使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:GrepResum 标签名&lt;/code&gt;可以快速打开以往的搜索结果&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Replace&lt;/code&gt;：对搜索到的结果执行文本替换&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;后续计划&quot;&gt;后续计划&lt;/h2&gt;

目前，这个插件只支持 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; 命令，后续计划增加 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ag&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rg&lt;/code&gt; 等命令支持。
</description>
        <pubDate>Sun, 07 May 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/introduce-new-vim-plugin-gfr-vim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/introduce-new-vim-plugin-gfr-vim/</guid>
        
        <category>vim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>将微信朋友圈移至静态网站</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#归因&quot; id=&quot;markdown-toc-归因&quot;&gt;归因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#我需要的朋友圈&quot; id=&quot;markdown-toc-我需要的朋友圈&quot;&gt;我需要的“朋友圈”&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#博客相册生成&quot; id=&quot;markdown-toc-博客相册生成&quot;&gt;博客相册生成&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

五一期间花了一点点时间将微信朋友圈“移植”到博客&lt;a href=&quot;../gallery/&quot;&gt;相册&lt;/a&gt;，今天抽空整理了下这个过程，并记录。

&lt;h3 id=&quot;归因&quot;&gt;归因&lt;/h3&gt;

微信朋友圈14年左右开始使用，至今已经十年了，出于以下原因放弃：

&lt;ol&gt;
  &lt;li&gt;不开放，只能微信里面，其他地方无法查看。&lt;/li&gt;
  &lt;li&gt;图片损伤，上传到朋友圈的照片会自动压缩，无法存储原图。&lt;/li&gt;
  &lt;li&gt;审查机制，不过多解释，虽然不喜欢讨论政治等敏感话题&lt;/li&gt;
  &lt;li&gt;永久存储，不确定哪一天微信会关闭&lt;/li&gt;
  &lt;li&gt;无法发链接，格式太受限&lt;/li&gt;
  &lt;li&gt;无法更新，过往内容无法更新&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;我需要的朋友圈&quot;&gt;我需要的“朋友圈”&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;开放的，输入网址即可访问，而非仅限于在微信内&lt;/li&gt;
  &lt;li&gt;内容自由的，自己可控的&lt;/li&gt;
  &lt;li&gt;安全的，内容存储于私密仓库，安全，易备份。&lt;/li&gt;
  &lt;li&gt;格式自由，虽然不需要富文本那么花俏，但是简单的 markdown 语法还是需要的&lt;/li&gt;
  &lt;li&gt;可更新&lt;/li&gt;
  &lt;li&gt;日志独立，可关联&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;博客相册生成&quot;&gt;博客相册生成&lt;/h3&gt;

最起初，只有三五个相册的时候，相册页面的内容是纯手工写的。后来，当把朋友圈老照片都转移过来后，手工操作的话就不合适了。

因为相册的内容比较简单：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{日期}

{context}

{gallery}

{location}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

因此，基于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev#autodoc&lt;/code&gt;API 写了一个脚本:
&lt;!--  --&gt;
&lt;div class=&quot;language-viml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:AUTODOC&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; SpaceVim#api#&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;dev#autodoc&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:AUTODOC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;autoformat &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; Gengallery&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; abort
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:AUTODOC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;begin &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^&amp;lt;!-- wsdjeg.net gallery start --&amp;gt;$&apos;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:AUTODOC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;end &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^&amp;lt;!-- wsdjeg.net gallery end --&amp;gt;$&apos;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:AUTODOC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;content_func &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;s:generate_gallery&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:AUTODOC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:generate_gallery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; abort
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; content &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;content&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:gallery_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; content &lt;span class=&quot;p&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; content
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:gallery_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; abort
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; text &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; gallery_dirs &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;globpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;docs/uploads&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; previous_t &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; gpath &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; gallery_dirs
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;previous_t&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;matchstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;gpath&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\d\+&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt;# previous_t 
      &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:dir_to_g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;gpath&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; previous_t &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;matchstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;gpath&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\d\+&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; text
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:dir_to_g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; abort
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str2nr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;matchstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\d\d\d\d&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str2nr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;matchstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\d\d\d\d\zs\d\d&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;matchstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\d\d\d\d\d\d\zs\d\d&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;### &apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;年&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;月&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; ? &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;日&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&quot; 如果存在 text.txt 文件，读取内容，写入文字&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;filereadable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/text.txt&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;readfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/text.txt&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{% include image-gallery-nofilename.html folder=&quot;&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;substitute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:],&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\&apos;, &apos;&lt;/span&gt;/&lt;span class=&quot;s1&quot;&gt;&apos;, &apos;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;) . &apos;&lt;/span&gt;&quot; %&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&apos;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;c&quot;&gt;&quot; 如果存在 location 文件，读取内容，写入地址&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;filereadable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/location&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;gt; &amp;lt;i class=&quot;fa fa-map-marker&quot;&amp;gt;&amp;lt;/i&amp;gt; &apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;readfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/location&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;!--  --&gt;
</description>
        <pubDate>Thu, 04 May 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/wechat-to-static-website/</link>
        <guid isPermaLink="true">https://wsdjeg.net/wechat-to-static-website/</guid>
        
        <category>gallery</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>五一假期·苏州一日游</title>
        <description>转眼间毕业已经十三年了，错过了大学同学毕业十年聚会，挺可惜的。一直想找时间回学校看看。

今天正好带着家人回学校转转，本以为假日期间在学校不会看到太多的人。但是到了之后发现，有很多都是带着小孩子到学校里面拍照、画画。

&lt;style&gt;
  .image-gallery {
    overflow: auto;
    margin-left: -1% !important;
  }
  .image-gallery li {
    float: left;
    display: block;
    padding:3px 3px;
    width: 19%;
  }
  .image-gallery li a {
    text-align: center;
    text-decoration: none !important;
    color: #777;
  }
  .image-gallery li a span {
    display: block;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    padding: 3px 0;
  }
  .image-gallery li a img {
    width: 100%;
    display: block;
  }
&lt;/style&gt;

&lt;ul class=&quot;image-gallery&quot;&gt;
  
&lt;/ul&gt;

午饭选的是“桃花源记”，进川菜馆吃苏帮菜，有点失误了。

下午去了“诚品书店”，以前空闲的时候过去，书店里人很少，很安静。是个不错的看书的地方，今天人有点太多了，有点赶集的味道。

&lt;style&gt;
  .image-gallery {
    overflow: auto;
    margin-left: -1% !important;
  }
  .image-gallery li {
    float: left;
    display: block;
    padding:3px 3px;
    width: 19%;
  }
  .image-gallery li a {
    text-align: center;
    text-decoration: none !important;
    color: #777;
  }
  .image-gallery li a span {
    display: block;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    padding: 3px 0;
  }
  .image-gallery li a img {
    width: 100%;
    display: block;
  }
&lt;/style&gt;

&lt;ul class=&quot;image-gallery&quot;&gt;
  
&lt;/ul&gt;

下一站去了圆融天幕，可惜不是晚上，没有看到夜景。

&lt;style&gt;
  .image-gallery {
    overflow: auto;
    margin-left: -1% !important;
  }
  .image-gallery li {
    float: left;
    display: block;
    padding:3px 3px;
    width: 19%;
  }
  .image-gallery li a {
    text-align: center;
    text-decoration: none !important;
    color: #777;
  }
  .image-gallery li a span {
    display: block;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    padding: 3px 0;
  }
  .image-gallery li a img {
    width: 100%;
    display: block;
  }
&lt;/style&gt;

&lt;ul class=&quot;image-gallery&quot;&gt;
  
&lt;/ul&gt;

开车来到了平江路，一眼望去乌泱泱的人，只能放弃这一站了，还有苏州地标大秋裤也没来得及去看，期待下次吧。
</description>
        <pubDate>Mon, 01 May 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/20230501/</link>
        <guid isPermaLink="true">https://wsdjeg.net/20230501/</guid>
        
        <category>苏大</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>《长空之王》观后感</title>
        <description>今天是大悦城开业活动的最后一天，以前这个地方叫博大摩登。原先人气一点也不旺，但是这次过来感觉确实很热闹。

&lt;style&gt;
  .image-gallery {
    overflow: auto;
    margin-left: -1% !important;
  }
  .image-gallery li {
    float: left;
    display: block;
    padding:3px 3px;
    width: 19%;
  }
  .image-gallery li a {
    text-align: center;
    text-decoration: none !important;
    color: #777;
  }
  .image-gallery li a span {
    display: block;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    padding: 3px 0;
  }
  .image-gallery li a img {
    width: 100%;
    display: block;
  }
&lt;/style&gt;

&lt;ul class=&quot;image-gallery&quot;&gt;
  
&lt;/ul&gt;

中午尝了一下新白鹿，一家不错的杭州菜。晚上看了一部电影，《长空之王》。实际上本来前天就想看了，周五晚上回来后在融创茂吃了个“等鱼柒·豆花烤鱼”，已经不记得是第几次吃这家了，小朋友似乎挺爱吃的。
完了本来想去看看电影，奈何时间太晚了，只能早早回去休息。

&lt;style&gt;
  .image-gallery {
    overflow: auto;
    margin-left: -1% !important;
  }
  .image-gallery li {
    float: left;
    display: block;
    padding:3px 3px;
    width: 19%;
  }
  .image-gallery li a {
    text-align: center;
    text-decoration: none !important;
    color: #777;
  }
  .image-gallery li a span {
    display: block;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    padding: 3px 0;
  }
  .image-gallery li a img {
    width: 100%;
    display: block;
  }
&lt;/style&gt;

&lt;ul class=&quot;image-gallery&quot;&gt;
  
&lt;/ul&gt;

第一次了解到试飞员这一高危的职业，希望每一次试飞都可以安全落地。

看似和平的年代，实际上有很多人在背后默默付出，默默守护。

电影中穿插着各种家庭的元素，有父母、有老婆孩子，虽然不舍，但是还是默默支持，默默承受着。

张大队那句“做为军人，性命加使命才是生命”真的太贴切了，看完整个人都久久的沉浸在这样的敬佩、感动和自豪中，致敬这样一群默默守护我们的人!

</description>
        <pubDate>Sun, 30 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/movie-review-Born-To-Fly/</link>
        <guid isPermaLink="true">https://wsdjeg.net/movie-review-Born-To-Fly/</guid>
        
        <category>movie</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>Neovim lua bindeval 解决方案</title>
        <description>最近在&lt;a href=&quot;https://github.com/SpaceVim/SpaceVim/pull/4823&quot;&gt;改写插件 tagbar 的日志系统&lt;/a&gt;，采用 SpaceVim 内置的日志插件。但是在调用 debug 函数时发现日志一直无法写入。

代码逻辑非常简单，lua 文件逻辑：

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lua/spacevim/logger.lua&lt;/code&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_debug_mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_debug_mode&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

vim script 这边只定义了一个函数：

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoload/testl.vim&lt;/code&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; testl#test&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; abort
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;luaeval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;require(&quot;testluaeval&quot;).test()&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

测试步骤：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let tlog = testl#test()
let tlog._debug_mode = v:true
call tlog.debug(&apos;hello&apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

运行到此处发现，消息并没有被打印。于是在 neovim 仓库提交了&lt;a href=&quot;https://github.com/neovim/neovim/issues/22863&quot;&gt;issue&lt;/a&gt;。得到的回复是，目前 neovim 还不支持 bindeval，但是支持 closures。

因此逻辑上做了如下改动：

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lua/spacevim/logger.lua&lt;/code&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_debug_mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_debug_mode&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;start_debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_debug_mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;stop_debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_debug_mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

vim script 这边只定义了一个函数：

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoload/testl.vim&lt;/code&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; testl#test&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; abort
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;luaeval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;require(&quot;testluaeval&quot;).test()&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

测试步骤：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let tlog = testl#test()
call tlog.start_debug()
call tlog.debug(&apos;hello&apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

通过以上的改动，测试步骤可以达到预期效果。
</description>
        <pubDate>Mon, 03 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/workaround-for-neovim-lua-bindeval/</link>
        <guid isPermaLink="true">https://wsdjeg.net/workaround-for-neovim-lua-bindeval/</guid>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>《忠犬八公》观后感</title>
        <description>结束了一周的出差，周五到家后，习惯性的看看有什么好看的电影上映。正好看到《忠犬八公》上映。

&lt;img src=&quot;../images/20230331.jpg&quot; alt=&quot;&quot; /&gt;

刚开始还有一些疑惑，因为这部电影我记得很早以前就看过。仔细看来原来是大陆拍的，以前看的另外一个版本。

晚饭后，一家人一起去，正好赶上 7:20 这场。

可能是因为以前看过了，对剧情也大概有了心理预知，所以剧情上倒没有什么特别大的感触。

但是期间一些细节也让我感触很多：

&lt;ol&gt;
  &lt;li&gt;教授第一次发飙讲的那段话，其实也很在理。人生匆匆几十年（现在已经过一小半了），没有什么比喜欢更重要。&lt;/li&gt;
  &lt;li&gt;教授妻子嘴上太伤人，但是其实内心还是很关心教授和八筒，也许她喜欢八筒只是爱屋及乌。&lt;/li&gt;
  &lt;li&gt;教授送儿子这段，父亲和母亲表达爱的方式还是有区别的。突然让我想到父亲送我上大学的那天，临走时，我秦楚地看到，父亲的眼睛很红。也是，以往都是离家很近上学。上了大学之后，包括现在工作了以后，回去的机会太少了。&lt;/li&gt;
  &lt;li&gt;儿子一直被误会在瞎折腾，倔强的坚持着他人看不懂的东西，最后实现自己的目标时开心。想想也是，很多时候，自己觉得对即可。&lt;/li&gt;
  &lt;li&gt;而最让我感触的，还是回忆结束后最后一段，看到满屋的报纸后，可以想象“八筒”日复一日的等了多久。&lt;/li&gt;
&lt;/ol&gt;

小狗的想法要比人类简单太多太多了，他的忠诚值得善待！

</description>
        <pubDate>Fri, 31 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/movie-review-Hachi-A-Dogs-Tale/</link>
        <guid isPermaLink="true">https://wsdjeg.net/movie-review-Hachi-A-Dogs-Tale/</guid>
        
        <category>movie</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>《保你平安》观后感</title>
        <description>今天晚上正好有时间，去看了下最新出来的电影《保你平安》。其实在看这部电影之前，已经对剧情做了大致的了解。

一开始，把这部剧当作一个喜剧来看的，看着看着代入感就太强了。

现在的网络环境确实挺糟糕的。虽然做到了实名制，但是实际上对于大众来说。网络论坛上出现的各种角色还是匿名的。你无法判断他到底是谁。

只能说，其实网络也不是法外之地，希望在网络上发表各种言论时。还是要有敬畏心理，慎言！

&lt;img src=&quot;../images/20230324.png&quot; alt=&quot;&quot; /&gt;

</description>
        <pubDate>Fri, 24 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/movie-review-Post-Truth/</link>
        <guid isPermaLink="true">https://wsdjeg.net/movie-review-Post-Truth/</guid>
        
        <category>movie</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>使用 Lua 重写 SpaceVim 内置插件</title>
        <description>最近如果你关注 Neovim 的社区，就会发现使用 Lua 开发的插件越来越多。

Neovim 默认就支持 luajit，早些时候，做过一次 luajit 与 vim script 速度的比较。

以下是一个测试的 Vim Script 脚本。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; Fibo&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;N&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; abort
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:N&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;73&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; tmp &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; tmp
        &lt;span class=&quot;k&quot;&gt;endwhile&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endwhile&lt;/span&gt;
    echo &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; LuaFibo&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;N&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; abort
&lt;span class=&quot;k&quot;&gt;lua&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; EOF
local &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;api&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;nvim_eval&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;str2nr(a:N)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;73&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;
        end
end

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;format&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;%d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
EOF
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...)&lt;/span&gt; abort
        &lt;span class=&quot;c&quot;&gt;&quot; for func in a:000&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; start &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reltime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a:2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; sec &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reltimefloat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reltime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;start&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;%s(%d): %.6g sec&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; sec&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;&quot; endfor&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

command&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;nargs&lt;span class=&quot;p&quot;&gt;=+&lt;/span&gt; TestFunc &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

载入以下脚本后执行如下命令可看到测试结果:

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:TestFunc Fibo 1000
:TestFunc Fibo 10000000
:TestFunc LuaFibo 1000
:TestFunc LuaFibo 10000000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

本地测试结果：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Fibo(1000): 0.410364 sec
Fibo(10000000): 1470.280914 sec
LuaFibo(1000): 9.052000e-4 sec
LuaFibo(10000000): 1.235385 sec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

通过以上简单的测试，可以明显看到 luajit 的速度比 Vim script 速度要快很多。
随着 Neovim 对 Lua 的推崇，已经出现了很多使用 Lua 开发的插件。
同时，一些知名的 Vim 插件也被使用 Lua 进行重写。

SpaceVim 中又不少内置的插件，比如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flygrep&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iedit&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;task-manager&lt;/code&gt; 等等。
这些插件原先使用的是 Vim script，为的是兼容 Vim 和 Neovim。

在最新版的 SpaceVim 中，部分插件已经使用 lua 重写了。当然了，原先的 Vim script 写的版本也保留下来了，以便于兼容 Vim。

目前已经重写的插件包括：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flygrep&lt;/code&gt;: 实时异步代码检索，根据输入的内容，实时展示代码搜索结果。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iedit&lt;/code&gt;: 类似于 emacs 的 iedit-mode，提供了多光标编辑的支持。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;todomanager&lt;/code&gt;: 项目待办事项管理&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 22 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/rewrite-spacevim-builtin-plugin-using-lua/</link>
        <guid isPermaLink="true">https://wsdjeg.net/rewrite-spacevim-builtin-plugin-using-lua/</guid>
        
        <category>vim</category>
        
        <category>neovim</category>
        
        <category>lua</category>
        
        <category>spacevim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>使用 Vim 作为 SSH 客户端</title>
        <description>在 Windows 下之前一直使用 xshell 作为 ssh 客户端。自从 Neovim 和 Vim 都增加了内置终端后，于是就把 xshell 这个软解卸载了。使用 Neovim 内置的函数来实现 SSH 连接。

首先，需要启用 SpaceVim 的 ssh 模块：

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;ssh&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;模块选项&quot;&gt;模块选项&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh_port&lt;/code&gt;: 设置服务器的 ssh 端口&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh_address&lt;/code&gt;: 设置服务器的地址或者 ip&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh_user&lt;/code&gt;: 设置默认的用户名&lt;/li&gt;
&lt;/ul&gt;

示例：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[[layers]]
    name = &apos;ssh&apos;
    ssh_command = &apos;D:\Programs\Git\usr\bin\ssh.exe&apos;
    ssh_user = &apos;root&apos;
    ssh_address = &apos;192.168.1.10&apos;
    ssh_port = &apos;8097&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;快捷键&quot;&gt;快捷键&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;快捷键&lt;/th&gt;
      &lt;th&gt;功能描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPC S o&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;打开 ssh 窗口&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</description>
        <pubDate>Mon, 10 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/use-vim-as-ssh-client/</link>
        <guid isPermaLink="true">https://wsdjeg.net/use-vim-as-ssh-client/</guid>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>安装并设置 Shadowsocks</title>
        <description>首先需要下载 &lt;a href=&quot;https://github.com/shadowsocks/shadowsocks-rust&quot;&gt;shadowsocks-rust&lt;/a&gt;。可以使用 curl 直接下载：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl -fLo shadowsocks.tar.xz https://github.com/shadowsocks/shadowsocks-rust/releases/download/v1.15.0-alpha.4/shadowsocks-v1.15.0-alpha.4.x86_64-unknown-linux-gnu.tar.xz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

解压：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tar -xf shadowsocks.tar.xz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

解压完，在当前目录可以看到一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssserver&lt;/code&gt; 文件，添加可执行权限：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo chmod +x ssserver
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

新建配置文件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.json&lt;/code&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;my_server_ip&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server_port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8388&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;password&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mypassword&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;method&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;aes-256-gcm&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;local_address&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;local_port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1080&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行如下命令：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nohup ./ssserver -c config.json &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 03 Jun 2022 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/setup-shadowsocks/</link>
        <guid isPermaLink="true">https://wsdjeg.net/setup-shadowsocks/</guid>
        
        <category>vim</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>重新启用知乎账号</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#为什么注销知乎&quot; id=&quot;markdown-toc-为什么注销知乎&quot;&gt;为什么注销知乎&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#为什么重新启用知乎&quot; id=&quot;markdown-toc-为什么重新启用知乎&quot;&gt;为什么重新启用知乎&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;为什么注销知乎&quot;&gt;为什么注销知乎&lt;/h2&gt;

早在 2022 年的时候，我注销了自己的知乎老账号，有很长一段时间没再使用知乎。早期知乎使用还是比较多的，
上面也不少内容还是很有帮助的。但是不知道从什么时候开始，知乎每天推送的都是各种故事文字，
或者推送一些容易让人产生负面情绪的内容。

说到这，让我想起来以前似乎有个 Facebook 员工暴露社交平台推送的算法，似乎刻意将一些容易让人产生愤怒，
或者其他反差情绪的内容。或者推送一些有争议性的话题，以引起激烈的讨论。

&lt;h2 id=&quot;为什么重新启用知乎&quot;&gt;为什么重新启用知乎&lt;/h2&gt;

其实，如果从文章质量上来还，知乎上面还是有很多优质内容的，只不过需要自己精心去筛选阅读。

我的回答：

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.zhihu.com/question/23427617/answer/1993096050655918014&quot;&gt;如何构建自己的笔记系统？&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Fri, 20 May 2022 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/cancel-zhihu-account/</link>
        <guid isPermaLink="true">https://wsdjeg.net/cancel-zhihu-account/</guid>
        
        <category>zhihu</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>想对微博说 FUCK</title>
        <description>今天下班后，回来本来想上微博看看最近有什么新鲜的事情。结果出现了这样一幕：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/168807405-521e90e7-7da6-43ae-9a91-9cdb860fc6a1.png&quot; alt=&quot;fuck-weibo&quot; /&gt;

瞬间感觉人都不好了。很多好友，历史消息都还没有任何备份。所以说，现在完全不能依赖这类所谓的社交软件。后台管理员有无限大的权限。

</description>
        <pubDate>Tue, 17 May 2022 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/fuck-weibo-com/</link>
        <guid isPermaLink="true">https://wsdjeg.net/fuck-weibo-com/</guid>
        
        <category>vim</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>nvim-tree.lua 使用初体验</title>
        <description>使用 Vim 有很长一段时间了，我记得最早期的时候，
还是在网上看各种 Vim 配置的教程。
而这些教程里面，大部分都会提到一个叫做文件树（File Explorer）的功能。

文件树插件，也是我日常使用 Vim 必备的插件。
刚开始接触 Vim 的时候，那时候插件还很少，
只有内置的 &lt;a href=&quot;https://www.vim.org/scripts/script.php?script_id=1075&quot;&gt;netrw&lt;/a&gt;。
后来接触到了 &lt;a href=&quot;https://github.com/preservim/nerdtree&quot;&gt;nerdtree&lt;/a&gt; 以及
Shougo 的&lt;a href=&quot;https://github.com/Shougo/vimfiler.vim&quot;&gt;vimfiler&lt;/a&gt;，
包括 Shougo 使用 neovim remote 插件特性重写的 &lt;a href=&quot;https://github.com/Shougo/defx.nvim&quot;&gt;defx.nvim&lt;/a&gt;。

目前，SpaceVim 已经支持了以上这些文件树插件，可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filemanager&lt;/code&gt; 选项进行设置：

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;filemanager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nerdtree&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

Neovim 这一项目目前默认支持 lua，很多插件被使用 lua 重写，
文件树也不例外。
最近就看到一个不错的文件树插件&lt;a href=&quot;https://github.com/kyazdani42/nvim-tree.lua&quot;&gt;nvim-tree.lua&lt;/a&gt;，
计划给 SpaceVim 也&lt;a href=&quot;https://github.com/SpaceVim/SpaceVim/pull/4668&quot;&gt;增加这个插件支持&lt;/a&gt;。在次之前，先体验一下这个插件到底有哪些功能：

测试版本：&lt;a href=&quot;https://github.com/kyazdani42/nvim-tree.lua/tree/9049f364cc3ceaff07ab130e1d35aec9e4124563&quot;&gt;nvim-tree.lua@9049f364&lt;/a&gt;

启用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim-tree&lt;/code&gt;:

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;filemanager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nvim-tree&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/167356197-41fe5647-54db-4435-b8cd-48930eda457d.png&quot; alt=&quot;image&quot; /&gt;

&lt;h2 id=&quot;存在的问题&quot;&gt;存在的问题&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    如果当前目录修改后，再使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:NvimTreeFindFile&lt;/code&gt; 无法发现当前文件。
  &lt;/li&gt;
  &lt;li&gt;
    禁用默认的快捷键
  &lt;/li&gt;
&lt;/ol&gt;

尝试搜索文档和&lt;a href=&quot;https://github.com/kyazdani42/nvim-tree.lua/issues?q=is%3Aissue+is%3Aopen+disable+key+binding&quot;&gt;issues&lt;/a&gt;，最终只找到一个：&lt;a href=&quot;https://github.com/kyazdani42/nvim-tree.lua/issues/448#issuecomment-871685261&quot;&gt;Default keymaps cannot be unset&lt;/a&gt;。
里面有一段回复：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim.g.nvim_tree_disable_default_keybindings = 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

但是，设置后，启动就警告：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[NvimTree] Following options were moved to setup, see bit.ly/3vIpEOJ: nvim_tree_disable_default_keybindings
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Mon, 09 May 2022 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/first-experience-with-nvim-tree/</link>
        <guid isPermaLink="true">https://wsdjeg.net/first-experience-with-nvim-tree/</guid>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>如何使用 SpaceVim 的 Job API</title>
        <description>因为 Vim8 和 Neovim 实现的 job 函数存在很大的区别，并且使用的方式也是不一样的。在制作插件时，如果需要同时兼容 Vim 和 Neovim 就会存在很大的麻烦。因此，在 SpaceVim 中，实现了一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;job API&lt;/code&gt;，使用示例如下：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;s:JOB&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; SpaceVim#api#&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;job&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;echo&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;hello world&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; event&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;&quot; the data is a list of string&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:data&lt;/span&gt;
        echo &lt;span class=&quot;nb&quot;&gt;line&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endf&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:JOB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s:command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;on_stdout&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;s:stdout&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这个 API 的实现，参考了 neovim job 的模型。支持如下参数：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_stdout&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_stderr&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_exit&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 03 May 2022 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/how-to-use-spacevim-job-api/</link>
        <guid isPermaLink="true">https://wsdjeg.net/how-to-use-spacevim-job-api/</guid>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>使用 Vim 作为聊天客户端</title>
        <description>目前，使用较多的聊天室是 SpaceVim 的 gitter 聊天室，但是这个平台网页访问比较慢。
因此做了&lt;a href=&quot;https://github.com/wsdjeg/vim-chat&quot;&gt;vim-chat&lt;/a&gt;，可以在 Vim/Neovim 里面快速打开聊天室进行沟通。

&lt;img src=&quot;https://files.gitter.im/5af54775d73408ce4f98ed8a/16ky/image.png&quot; alt=&quot;vim-chat&quot; /&gt;

如果有兴趣的，可以自行尝试。这个插件目前开发是在 spacevim 的主仓库，自动更新独立仓库，因此有两种使用方式。你可以在 spacevim 里启用 &lt;a href=&quot;https://spacevim.org/layers/chat/&quot;&gt;chat&lt;/a&gt; 模块，也可以单独安装vim-chat插件。
</description>
        <pubDate>Mon, 02 May 2022 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/use-vim-as-a-chat-client/</link>
        <guid isPermaLink="true">https://wsdjeg.net/use-vim-as-a-chat-client/</guid>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>下载安装winrar，并激活去广告</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#下载&quot; id=&quot;markdown-toc-下载&quot;&gt;下载&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#激活&quot; id=&quot;markdown-toc-激活&quot;&gt;激活&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#去广告&quot; id=&quot;markdown-toc-去广告&quot;&gt;去广告&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;下载&quot;&gt;下载&lt;/h2&gt;

在 winrar官网（https://www.rarlab.com/download.htm）下载，并安装。

&lt;h2 id=&quot;激活&quot;&gt;激活&lt;/h2&gt;

在winrar目录新建&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rarreg.key&lt;/code&gt;文件，输入以下内容并保存：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;RAR registration data

wncn
Unlimited Company License
UID=1b064ef8b57de3ae9b52
64122122509b52e35fd885373b214a4a64cc2fc1284b77ed14fa20
66ebfca6509f9813b32960fce6cb5ffde62890079861be57638717
7131ced835ed65cc743d9777f2ea71a8e32c7e593cf66794343565
b41bcf56929486b8bcdac33d50ecf7739960627351a9ef03353a0e
592b327cd80645472f0ee622d1915028a9e05298e593db36384f0f
f46afd5fed9b0bd095d1788266b81494b976f78fb1c551ca60a054
b17ad853ab902058b42c6887e1b3d40e0b45abf37de02106056887
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;去广告&quot;&gt;去广告&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    下载 &lt;a href=&quot;https://8dx.pc6.com/hc6/ResourceHacker_v5.1.8.exe&quot;&gt;ResourceHacker.exe&lt;/a&gt;, 运行该工具打开winrar安装目录内的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;winrar.exe&lt;/code&gt;文件：
  &lt;/li&gt;
  &lt;li&gt;
    定位到String Table（字符串）
  &lt;/li&gt;
&lt;/ul&gt;

&lt;img src=&quot;../images/winrar-1.png&quot; alt=&quot;&quot; /&gt;

&lt;ul&gt;
  &lt;li&gt;定位并打开80：2052&lt;/li&gt;
&lt;/ul&gt;

&lt;img src=&quot;../images/winrar-2.png&quot; alt=&quot;&quot; /&gt;

&lt;ul&gt;
  &lt;li&gt;删除1277所在整行，点击运行，然后保存。&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Sat, 19 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/activate-winrar/</link>
        <guid isPermaLink="true">https://wsdjeg.net/activate-winrar/</guid>
        
        <category>winrar</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>在 SpaceVim 中启自动保存</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#前因&quot; id=&quot;markdown-toc-前因&quot;&gt;前因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#基本配置&quot; id=&quot;markdown-toc-基本配置&quot;&gt;基本配置&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

使用 Vim 有一段时间了，SpaceVim 也陆续出了好几个版本。自动保存这个功能一直没有加上，其实并不是没有这个需求，而是没有找到合适的逻辑去实现。最新版SpaceVim新增了自动保存的功能，当然这一功能默认是关闭的。下面来简单介绍一下如何启用自动保存功能。

&lt;h2 id=&quot;前因&quot;&gt;前因&lt;/h2&gt;

再使用Vim编辑代码时，经常会出现无意间关闭了Vim，或者各种插件问题导致Vim不能正常工作。忘记保存文件而导致文件编辑内容丢失。不知道大家有没有遇到过，我自己时遇到过好多次。最近，刚刚用上win11，发现office左上角自带了一个自动保存按钮。突然脑洞大开，是时候给SpaceVim也增加这一功能了。

再网上搜索了vim自动保存，发现有不少的插件提供这一功能，总的来说有如下两种逻辑：

1、将文件定期保存到指定的备份文件夹，比如~/.vim/backup

2、定期执行:w命令。

我更倾向于后者。

&lt;h2 id=&quot;基本配置&quot;&gt;基本配置&lt;/h2&gt;

自动保存功能，包含在edit模块里面，可以通过如下配置进行设置：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[[layers]]
    name = &apos;edit&apos;
    autosave_timeout = 300000
    autosave_events = [&apos;InsertLeave&apos;, &apos;TextChanged&apos;]
    autosave_all_buffers = false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

目前 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edit&lt;/code&gt; 模块支持如下配置选项：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autosave_timeout&lt;/code&gt;: 设置自动保存的时间间隔，默认是0，表示未开启定时自动保存。这个选项设定的值需要是毫秒数，并且需要小于100*60*1000 (100 分钟) 且 大于1000（1分钟）。比如设定成每隔5分钟自动保存一次：
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[[layers]]
  name = &apos;edit&apos;
  autosave_timeout = 300000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autosave_events&lt;/code&gt;: 设定自动保存依赖的Vim事件，默认是空表。比如需要在离开插入模式时或者内容改变时自动保存：
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[[layers]]
  name = &apos;edit&apos;
  autosave_events = [&apos;InsertLeave&apos;, &apos;TextChanged&apos;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autosave_all_buffers&lt;/code&gt;: 设定是否需要保存所有文件，默认是只保存当前编辑的文件，如果该选项设定成&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;则保存所有文件。
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[[layers]]
  name = &apos;edit&apos;
  autosave_all_buffers = true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autosave_location&lt;/code&gt;: 设定保存文件的位置，默认为空，表示保存为原始路径。也可以设定成一个备份文件夹，自动保存的文件保存到指定的备份文件夹里面，而不修改原始文件。
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[[layers]]
  name = &apos;edit&apos;
  autosave_location = &apos;~/.cache/backup/&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 06 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/setup-autosave-in-spacevim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/setup-autosave-in-spacevim/</guid>
        
        <category>spacevim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Window 7 下安装 nodejs</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#安装-nodejs&quot; id=&quot;markdown-toc-安装-nodejs&quot;&gt;安装 nodejs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;安装-nodejs&quot;&gt;安装 nodejs&lt;/h2&gt;

在 Windows 下使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scoop install nodejs&lt;/code&gt; 后，发现安装的是 nodejs16，运行提示：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;无法定位程序输入点GetHostNameW于动态链接库WS2_32.dll上。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

估计是版本太新，系统不兼容，尝试 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scoop uninstall nodejs&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scoop install nodejs-lst&lt;/code&gt;，
之后运行还是这鬼样子。google搜了一圈，没找到合适的解释。直接：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scoop uninstall nodejs-lst
scoop install nodejs11
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sat, 02 Oct 2021 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/install-nodejs-in-win7/</link>
        <guid isPermaLink="true">https://wsdjeg.net/install-nodejs-in-win7/</guid>
        
        <category>nodejs</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>配置 zig 的 Vim 开发环境</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#安装zig语言&quot; id=&quot;markdown-toc-安装zig语言&quot;&gt;安装zig语言&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#基本运行&quot; id=&quot;markdown-toc-基本运行&quot;&gt;基本运行&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#语言语法&quot; id=&quot;markdown-toc-语言语法&quot;&gt;语言语法&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#代码格式化&quot; id=&quot;markdown-toc-代码格式化&quot;&gt;代码格式化&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;安装zig语言&quot;&gt;安装zig语言&lt;/h2&gt;

我使用的是 Win7 操作系统，从官网下载最新版 &lt;a href=&quot;https://ziglang.org/builds/zig-windows-x86_64-0.7.1+dfacac916.zip&quot;&gt;zig-windows-x86_64-0.7.1+dfacac916.zip&lt;/a&gt;，解压后，发现：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/103470501-edd87900-4dad-11eb-85a5-042c65818995.png&quot; alt=&quot;image&quot; /&gt;

zig 目录下只有一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zig.exe&lt;/code&gt; 命令，没有其他的了，这就简单了，直接把这个目录加 PATH 就行，
因为我使用的是 SpaceVim，不需要修改系统环境变量，直接载入 lang#zig 模块。

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;lang#zig&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在启动函数加一句：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let $PATH .= &apos;;D:\zig&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

完成以上的步骤，基本上可以在 Vim 里面使用 zig 语言相关命令了。

&lt;h2 id=&quot;基本运行&quot;&gt;基本运行&lt;/h2&gt;

在 SpaceVim 里面，运行当前 zig 文件的快捷键是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPC l r&lt;/code&gt;，
这个快捷键实际上是异步运行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zig run&lt;/code&gt; 加上当前文件名。

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/103470513-1a8c9080-4dae-11eb-8527-ac08bcb16f6d.png&quot; alt=&quot;image&quot; /&gt;

第一次运行，发现时间是9秒，不知道为什么会这么慢，但是后来的时间都是 0.14 秒左右，可能跟我的电脑有关，比较老了。

&lt;h2 id=&quot;语言语法&quot;&gt;语言语法&lt;/h2&gt;

基本环境搭建好了，那么就是开始学习基本语法了，瞅了一眼官方文档，发现有一些内容跟 rust 很像，不过总体来说，感觉语法还是有点复杂。

&lt;h2 id=&quot;代码格式化&quot;&gt;代码格式化&lt;/h2&gt;

zig 命令提供了一个 zig fmt 的子命令，想测试下如何格式化代码，执行直接报错，zig run 没问题：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/103470528-54f62d80-4dae-11eb-98c1-04d29e834f65.png&quot; alt=&quot;image&quot; /&gt;

这种奇葩问题不该只有我一个人遇到吧，于是谷歌搜了一波，发现两个 github 的 issue：&lt;a href=&quot;https://github.com/ziglang/zig/issues/725&quot;&gt;#725&lt;/a&gt;，&lt;a href=&quot;https://github.com/ziglang/zig/issues/4605&quot;&gt;#4605&lt;/a&gt;

Github issue 已开，等坑被填了再来试试： &lt;a href=&quot;https://github.com/ziglang/zig/issues/7654&quot;&gt;#7654&lt;/a&gt;

</description>
        <pubDate>Sun, 03 Jan 2021 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/setup-vim-as-zig-ide/</link>
        <guid isPermaLink="true">https://wsdjeg.net/setup-vim-as-zig-ide/</guid>
        
        <category>zig</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>字符串编辑距离算法</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#代码实现&quot; id=&quot;markdown-toc-代码实现&quot;&gt;代码实现&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#参考资料&quot; id=&quot;markdown-toc-参考资料&quot;&gt;参考资料&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;代码实现&quot;&gt;代码实现&lt;/h2&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chars1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.chars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.collect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chars2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.chars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.collect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.chars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.chars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;vec!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;vec!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chars1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chars2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;cost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;substitution&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;substitution&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;len1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;len2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wsdjeg&quot;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.to_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;wdsjgh&quot;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.to_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;参考资料&quot;&gt;参考资料&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.dreamxu.com/books/dsa/dp/edit-distance.html&quot;&gt;编辑距离 Edit distance&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Tue, 24 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/rust-edit-distance/</link>
        <guid isPermaLink="true">https://wsdjeg.net/rust-edit-distance/</guid>
        
        <category>rust</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Rust 模块与项目文件组织</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#什么是模块&quot; id=&quot;markdown-toc-什么是模块&quot;&gt;什么是模块&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#引入文件&quot; id=&quot;markdown-toc-引入文件&quot;&gt;引入文件&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#同级目录相互访问&quot; id=&quot;markdown-toc-同级目录相互访问&quot;&gt;同级目录相互访问&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#引用本地crate&quot; id=&quot;markdown-toc-引用本地crate&quot;&gt;引用本地crate&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#参考文章&quot; id=&quot;markdown-toc-参考文章&quot;&gt;参考文章&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;什么是模块&quot;&gt;什么是模块&lt;/h2&gt;

刚开始接触Rust的时候很多示例代码都是单文件的，随着学习的深入，单个文件里面的代码量越来越大。
此时就需要将单个文件拆分成多个文件。Rust里面关键字&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod&lt;/code&gt;可以用来定义一个模块，或者载入一个模块文件。

&lt;h2 id=&quot;引入文件&quot;&gt;引入文件&lt;/h2&gt;

假定，我们拥有如下文件结构：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rustmod
├── Cargo.toml
└── src
    └── main.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此时，新建一个文件&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/util.rs&lt;/code&gt;，加入如下内容：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hello_mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hello mod&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此时，就可以在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main.rs&lt;/code&gt;内使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod util&lt;/code&gt;引入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;util.rs&lt;/code&gt;文件了：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hello_mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码块，使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod util;&lt;/code&gt;载入模块文件，同时在main函数里调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;util::hello_mod()&lt;/code&gt;函数，需要说明的是，该函数需要使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pub&lt;/code&gt;
关键字进行申明。

&lt;h3 id=&quot;同级目录相互访问&quot;&gt;同级目录相互访问&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rustmod
├── Cargo.toml
└── src
    ├── main.rs
    ├── function.rs
    └── util.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

比如，在编写 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function.rs&lt;/code&gt; 内代码时，偶尔需要使用到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uril.rs&lt;/code&gt;里面一些常用的工具函数，该如何操作呢？

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// rustmod/src/function.rs&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hello_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hello_mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;引用本地crate&quot;&gt;引用本地crate&lt;/h3&gt;

假定有如下目录结构：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rustmod
├── Cargo.toml
└── src
    ├── main.rs
    ├── function.rs
    └── util.rs
xxx
├── Cargo.toml
└── src
    └── lib.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

修改&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustmod/Cargo.toml&lt;/code&gt;：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[package]
name = &quot;testmod&quot;
version = &quot;0.1.0&quot;
authors = [&quot;Shidong Wang&quot;]
edition = &quot;2018&quot;

[dependencies]
xxx = {path= &quot;../xxx&quot; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此时，就可以在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustmod/src/main.rs&lt;/code&gt;内通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extern crate xxx;&lt;/code&gt;来引入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xxx&lt;/code&gt;，修改&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main.rs&lt;/code&gt;：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xxx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;xxx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xxx_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;xxx_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;参考文章&quot;&gt;参考文章&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/46487796&quot;&gt;Rust的模块系统初探&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/73544030&quot;&gt;Rust 模块和文件 - (译)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/113038358&quot;&gt;Rust模块的理解&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 22 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/rust-modules-and-files/</link>
        <guid isPermaLink="true">https://wsdjeg.net/rust-modules-and-files/</guid>
        
        <category>rust</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Rust 读取标准输入</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#基本实现&quot; id=&quot;markdown-toc-基本实现&quot;&gt;基本实现&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#参考资料&quot; id=&quot;markdown-toc-参考资料&quot;&gt;参考资料&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

在写一个 rust 小工具，需要通过参数读取文件内容，以往使用的一些工具，除了支持通过参数读取指定
文件内容之外，还支持读取 stdin。比如：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cat test.py | python
python test.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;基本实现&quot;&gt;基本实现&lt;/h2&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BufRead&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;stdin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdin&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.unwrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;参考资料&quot;&gt;参考资料&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/30186037/how-can-i-read-a-single-line-from-stdin&quot;&gt;How can I read a single line from stdin?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 17 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/handle-stdin-in-rust/</link>
        <guid isPermaLink="true">https://wsdjeg.net/handle-stdin-in-rust/</guid>
        
        <category>rust</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Rust 字符串算法</title>
        <description>
在搜索 Rust 相关资料，无意间看到 v2ex 上面的一些字符串相关的问题，
于是使用 rust 来测试下。

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://v2ex.com/t/648140&quot;&gt;第 1 期: 前端算法精选-字符串系列&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

题目

给定一个字符串，请你找出其中不含有重复字符的 最长子串 的长度。

&lt;ul&gt;
  &lt;li&gt;示例 1：&lt;/li&gt;
&lt;/ul&gt;

输入: “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”，所以其长度为 3

&lt;ul&gt;
  &lt;li&gt;示例 2：&lt;/li&gt;
&lt;/ul&gt;

输入: “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”，所以其长度为 1。

&lt;ul&gt;
  &lt;li&gt;示例 3：&lt;/li&gt;
&lt;/ul&gt;

输入: “pwwkew” 输出: 3 解释: 因为无重复字符的最长子串是 “wke”，所以其长度为 3。 请注意，你的答案必须是 子串 的长度，”pwke” 是一个子序列，不是子串。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find_longest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;aaaa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find_longest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rst&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.chars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.contains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rst&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;rst&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rst&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 15 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/rust-string-algorithm/</link>
        <guid isPermaLink="true">https://wsdjeg.net/rust-string-algorithm/</guid>
        
        <category>rust</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Vim 字典补全插件</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#简单实现&quot; id=&quot;markdown-toc-简单实现&quot;&gt;简单实现&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#命令行工具&quot; id=&quot;markdown-toc-命令行工具&quot;&gt;命令行工具&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

因为需要书写一些英文文档，有些英文单词太长，因此需要一个英文单词补全工具。
之前在 Linux 系统下面使用了 look 命令，和 &lt;a href=&quot;https://github.com/ujihisa/neco-look&quot;&gt;noco-look&lt;/a&gt; 插件。但是换到 Windows
下之后，发现居然没有 look 这个命令。

恰巧，最近在学习 rust，于是就用 rust 简单写了一个字典补全的 Vim 插件：&lt;a href=&quot;https://github.com/wsdjeg/vim-async-dict&quot;&gt;vim-async-dict&lt;/a&gt;

&lt;h2 id=&quot;简单实现&quot;&gt;简单实现&lt;/h2&gt;

因为现有的工具已经非常齐全了，因此并未从头实现，补全框架使用的是 deoplete，
只需要新建一个 dict source：

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os.path&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expanduser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expandvars&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subprocess&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;.base&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Base&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;[D]&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min_pattern_length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;命令行工具&quot;&gt;命令行工具&lt;/h2&gt;

有了 source 之后，需要在新建一个命令行工具，接受 2 个参数，查询词和字典文件路径：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Config&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;#[allow(dead_code)]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;static&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;not enough arguments&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Config&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sat, 14 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/rust-async-dict-vim-plugin/</link>
        <guid isPermaLink="true">https://wsdjeg.net/rust-async-dict-vim-plugin/</guid>
        
        <category>vim</category>
        
        <category>rust</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>rust 格式化整理</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#基本用法&quot; id=&quot;markdown-toc-基本用法&quot;&gt;基本用法&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#进制转换&quot; id=&quot;markdown-toc-进制转换&quot;&gt;进制转换&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#对齐方式&quot; id=&quot;markdown-toc-对齐方式&quot;&gt;对齐方式&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;基本用法&quot;&gt;基本用法&lt;/h2&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ssss&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;进制转换&quot;&gt;进制转换&lt;/h2&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 默认用法,打印Display&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:o}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 八进制&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:x}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 十六进制 小写&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:X}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 十六进制 大写&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:p}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 指针&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:b}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 二进制&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:e}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;10000f32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 科学计数(小写)&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:E}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;10000f32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 科学计数(大写)&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:?}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 打印Debug&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:#?}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;test2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 带换行和缩进的Debug打印&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{a} {b} {b}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 命名参数&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;对齐方式&quot;&gt;对齐方式&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt;: 右对齐&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt;: 左对齐&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^&lt;/code&gt;: 居中对齐&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// @question 关于字符串对齐&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{0:&amp;gt;0w$}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 八进制&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;format_string := &amp;lt;text&amp;gt; [ format &amp;lt;text&amp;gt; ] *
format := &apos;{&apos; [ argument ] [ &apos;:&apos; format_spec ] &apos;}&apos;
argument := integer | identifier

format_spec := [[fill]align][sign][&apos;#&apos;][0][width][&apos;.&apos; precision][type]
fill := character
align := &apos;&amp;lt;&apos; | &apos;^&apos; | &apos;&amp;gt;&apos;
sign := &apos;+&apos; | &apos;-&apos;
width := count
precision := count | &apos;*&apos;
type := identifier | &apos;&apos;
count := parameter | integer
parameter := integer &apos;$&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sat, 07 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/format-macro-in-rust/</link>
        <guid isPermaLink="true">https://wsdjeg.net/format-macro-in-rust/</guid>
        
        <category>rust</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>开始学习 Rust</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#写在前面&quot; id=&quot;markdown-toc-写在前面&quot;&gt;写在前面&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#1-第一个程序&quot; id=&quot;markdown-toc-1-第一个程序&quot;&gt;1. 第一个程序&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#2-基本语法&quot; id=&quot;markdown-toc-2-基本语法&quot;&gt;2. 基本语法&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#21-注释&quot; id=&quot;markdown-toc-21-注释&quot;&gt;2.1 注释&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#22-变量&quot; id=&quot;markdown-toc-22-变量&quot;&gt;2.2 变量&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#23-函数&quot; id=&quot;markdown-toc-23-函数&quot;&gt;2.3 函数&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#24-基本数据类型&quot; id=&quot;markdown-toc-24-基本数据类型&quot;&gt;2.4 基本数据类型&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#25-操作符&quot; id=&quot;markdown-toc-25-操作符&quot;&gt;2.5 操作符&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#26-流程控制&quot; id=&quot;markdown-toc-26-流程控制&quot;&gt;2.6 流程控制&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#3-其他数据类型&quot; id=&quot;markdown-toc-3-其他数据类型&quot;&gt;3. 其他数据类型&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#31-结构体struct&quot; id=&quot;markdown-toc-31-结构体struct&quot;&gt;3.1 结构体(struct)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#32-枚举&quot; id=&quot;markdown-toc-32-枚举&quot;&gt;3.2 枚举&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#33-实现方法和接口impl--trait&quot; id=&quot;markdown-toc-33-实现方法和接口impl--trait&quot;&gt;3.3 实现方法和接口(impl &amp;amp; trait)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#34-泛型generics&quot; id=&quot;markdown-toc-34-泛型generics&quot;&gt;3.4 泛型(Generics)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#35-常见集合-vec&quot; id=&quot;markdown-toc-35-常见集合-vec&quot;&gt;3.5 常见集合 Vec&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#36-常见集合-string&quot; id=&quot;markdown-toc-36-常见集合-string&quot;&gt;3.6 常见集合 String&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#37-常见集合-hashmap&quot; id=&quot;markdown-toc-37-常见集合-hashmap&quot;&gt;3.7 常见集合 HashMap&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#4-错误处理&quot; id=&quot;markdown-toc-4-错误处理&quot;&gt;4 错误处理&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#41-不可恢复错误-panic&quot; id=&quot;markdown-toc-41-不可恢复错误-panic&quot;&gt;4.1 不可恢复错误 panic!&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#42-可恢复错误-result&quot; id=&quot;markdown-toc-42-可恢复错误-result&quot;&gt;4.2 可恢复错误 Result&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#5-包crate和模块&quot; id=&quot;markdown-toc-5-包crate和模块&quot;&gt;5 包、crate和模块&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#51-包和-crate&quot; id=&quot;markdown-toc-51-包和-crate&quot;&gt;5.1 包和 crate&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#52-模块&quot; id=&quot;markdown-toc-52-模块&quot;&gt;5.2 模块&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#6-测试&quot; id=&quot;markdown-toc-6-测试&quot;&gt;6 测试&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#61-单元测试unit-tests&quot; id=&quot;markdown-toc-61-单元测试unit-tests&quot;&gt;6.1 单元测试(unit tests)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#62-集成测试integration-tests&quot; id=&quot;markdown-toc-62-集成测试integration-tests&quot;&gt;6.2 集成测试(integration tests)&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#7-生命周期&quot; id=&quot;markdown-toc-7-生命周期&quot;&gt;7 生命周期&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;写在前面&quot;&gt;写在前面&lt;/h2&gt;

rust 这门语言刚出来时，非常火，当时还没有中文的教程，官方仅有的一篇英文教程和examples。
于是对着英文教程，靠着自己蹩脚的英语啃了一遍。但是过了这么久，并且期间没在使用这门语言，
已经基本忘记了，唯一记得的就是 rust 里面提出了一个叫做“借”的概念，当时被绕了很久。

rust的安装非常简单，在windows下，只需要下载 &lt;a href=&quot;https://rust-lang.org/tools/install&quot;&gt;rustup-init.exe&lt;/a&gt; 后运行安装即可。

&lt;h2 id=&quot;1-第一个程序&quot;&gt;1. 第一个程序&lt;/h2&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main.rs&lt;/code&gt;:

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

运行非常简单，使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustc main.rs&lt;/code&gt;即可编译出一个可执行运行文件。

println 的一些用法：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}, {}!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;world&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Hello, world!&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{0}, {1}!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;world&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Hello, world!&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{greeting}, {name}!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;world&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Hello, world!&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello, &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Hello, world!&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;2-基本语法&quot;&gt;2. 基本语法&lt;/h2&gt;

&lt;h3 id=&quot;21-注释&quot;&gt;2.1 注释&lt;/h3&gt;

rust 的注释有两种，单行注释，和快注释：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 单行注释&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 行尾注释&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/*
    块注释
    */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;22-变量&quot;&gt;2.2 变量&lt;/h3&gt;

rust 中包括局部变量和全局变量，默认都是局部变量，并且都是不可变变量，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mut&lt;/code&gt; 标记为可变变量。

&lt;ul&gt;
  &lt;li&gt;局部变量&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 声明变量，但并不赋值&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 声明 bool 变量，并赋值&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;122&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;全局变量&lt;/li&gt;
&lt;/ul&gt;

rust中使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static&lt;/code&gt;关键字申明全局变量，全局变量的生命周期是整个程序，必须显式标明类型，不支持类型推导；

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// 不可变静态变量&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 可变静态变量&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;常量&lt;/li&gt;
&lt;/ul&gt;

常量的申明使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const&lt;/code&gt;，和全局变量一样，生命周期也是整个程序。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;23-函数&quot;&gt;2.3 函数&lt;/h3&gt;

函数使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fn&lt;/code&gt;来申明，例如：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

函数的参数需要指定类型，例如：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;the sum is:{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

函数的返回值默认是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;，如果需要有返回值，需要在函数签名里使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&amp;gt;&lt;/code&gt;指定：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;the sum is:{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 等同于 return a + b;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

Rust 是基于表达式的语言，程序的最后一句话需要省略分号，作为返回值，
当然 rust 也支持使用 return 提前返回，但是需要加上分号。

rust是一个基于表达式的语言，不过它也有语句。
rust只有两种语句：声明语句和表达式语句，其他的都是表达式。
基于表达式是函数式语言的一个重要特征，表达式总是返回值。

可以利用元组(tuple)返回多个值:

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{} + 1 = {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add_num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 10 + 1 = 11&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

函数指针也可以作为变量使用

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;高阶函数&lt;/li&gt;
&lt;/ul&gt;

Rust 还支持高阶函数 (high order function)，允许把闭包作为参数来生成新的函数：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;factory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;move&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}, {}, {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;closure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;closure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;closure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}, {}, {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;box_fn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;factory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;box_fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;box_fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;box_fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}, {}, {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add_num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;box_fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add_num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}, {}, {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;where 关键字的使用&lt;/li&gt;
&lt;/ul&gt;

约束的trait增加后，代码看起来就变得诡异了，这时候需要使用where从句：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Debug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:?}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// where 从句&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Debug&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:?}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 或者&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Debug&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{:?}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;发散函数&lt;/li&gt;
&lt;/ul&gt;

发散函数（diverging function）是rust中的一个特性。发散函数不返回，它使用感叹号!作为返回类型表示：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;diverging&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;world&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;diverging&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;panic!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;This function will never return&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;24-基本数据类型&quot;&gt;2.4 基本数据类型&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;布尔值(bool)&lt;/li&gt;
  &lt;li&gt;字符(char)&lt;/li&gt;
  &lt;li&gt;有符号整型(i8, i16, i32, i64, i128)&lt;/li&gt;
  &lt;li&gt;无符号整型(u8, u16, u32, u64, u128)&lt;/li&gt;
  &lt;li&gt;指针大小的有符号/无符号整型(isize/usize，取决于计算机架构，32bit 的系统上，isize 等价于i32)&lt;/li&gt;
  &lt;li&gt;浮点数(f32, f64)&lt;/li&gt;
  &lt;li&gt;数组(arrays)&lt;/li&gt;
&lt;/ul&gt;

数组(arrays)的长度是可不变的，动态/可变长数组可以使用 Vec (非基本数据类型)。

&lt;ul&gt;
  &lt;li&gt;元组(tuples)，由相同/不同类型元素构成，长度固定。&lt;/li&gt;
&lt;/ul&gt;

元组的长度也是不可变的，更新元组内元素的值时，需要与之前的值的类型相同。

&lt;ul&gt;
  &lt;li&gt;切片(slice)，指向一段内存的指针。&lt;/li&gt;
&lt;/ul&gt;

切片并没有拷贝原有的数组，只是指向原有数组的一个连续部分，行为同数组。访问切片指向的数组/数据结构，可以使用&amp;amp;操作符。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 全部&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [0, 4)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 全部&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [2, 3]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [2, 3, 4]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [1, 2, 3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;字符串(str)&lt;/li&gt;
&lt;/ul&gt;

在 Rust 中，str 是不可变的静态分配的一个未知长度的UTF-8字节序列。
&amp;amp;str 是指向该字符串的切片。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//a: &amp;amp;&apos;static str&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;你好, 世界!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// 多行字符串&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;line one
line two&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// 字符串转义&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;line one&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;line two&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// 也可以在字符串字面量前加上r来避免转义&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;r&quot;line one\nline two&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

Rust的数组是被表示为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[T;N]&lt;/code&gt;。其中&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt;表示数组大小，并且这个大小一定是个编译时就能获得的整数值，
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt;表示泛型类型，即任意类型。我们可以这么来声明和使用一个数组:

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;print!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

和Golang一样，Rust的数组中的N（大小）也是类型的一部分，
即&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[u8; 3] != [u8; 4]&lt;/code&gt;。这么设计是为了更安全和高效的使用内存，当然了，
这会给第一次接触类似概念的人带来一点点困难，比如以下代码。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;print!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{} &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码编译会报错，因为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;show(b);&lt;/code&gt; 传入的参数类型是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[u8, 4]&lt;/code&gt;,
但是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;show(arr: [u8, 3])&lt;/code&gt; 这个函数签名只接受&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[u8,3]&lt;/code&gt;。

因此可以使用切片（Slice），一个Slice的类型是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;[T]&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;mut [T]&lt;/code&gt;, 因此以上代码可以改为：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;print!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{} &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slice_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slice_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

字符串切片&amp;amp;str指向的字符串是静态分配的，在 Rust 中，有另一个堆分配的，
可变长的字符串类型String(非基本数据类型)。通常由字符串切片&amp;amp;str通过 to_string() 或 String::from() 方法转换得到。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.to_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;函数(functions)&lt;/li&gt;
&lt;/ul&gt;

函数指针也是基本数据类型，可以赋值给其他的变量

&lt;h3 id=&quot;25-操作符&quot;&gt;2.5 操作符&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;一元操作符&lt;/li&gt;
&lt;/ul&gt;

顾名思义，一元操作符是专门对一个Rust元素进行操纵的操作符，主要包括以下几个:

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;: 取负，用于数值类型。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;: 解引用，这是一个很有用的符号，和Deref（DerefMut）这个trait关联密切。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt;: 取反。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;mut&lt;/code&gt;: 租借，borrow。向一个owner租借其使用权，分别是租借一个只读使用权和读写使用权。&lt;/li&gt;
&lt;/ul&gt;

二元操作符

&lt;ul&gt;
  &lt;li&gt;算数操作符&lt;/li&gt;
&lt;/ul&gt;

算数运算符都有对应的trait的，他们都在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::ops&lt;/code&gt;下：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;: 加法。实现了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::ops::Add&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;: 减法。实现了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::ops::Sub&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;: 乘法。实现了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::ops::Mul&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;: 除法。实现了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::ops::Div&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt;: 取余。实现了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::ops::Rem&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// 包括: + - * / %&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//6&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//4&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//10&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//2 not 2.5&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//1&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5.0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//2.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;比较运算符&lt;/li&gt;
&lt;/ul&gt;

比较运算符其实也是某些trait的语法糖啦，
不同的是比较运算符所实现的trait只有两个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::cmp::PartialEq&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::cmp::PartialOrd&lt;/code&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// == = != &amp;lt; &amp;gt; &amp;lt;= &amp;gt;=&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//false&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//true&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//true&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//false&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//true&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//true&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//true&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;&apos;a&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;逻辑运算符&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c1&quot;&gt;// ! &amp;amp;&amp;amp; ||&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//false&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//false&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//true&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// rust 的逻辑运算符是惰性boolean运算符&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// @question 什么是惰性boolean运算符&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;位运算符&lt;/li&gt;
&lt;/ul&gt;

和算数运算符差不多的是，位运算也有对应的trait。

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt;: 与操作。实现了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::ops::BitAnd&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt;: 或操作。实现了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::ops::BitOr&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^&lt;/code&gt;: 异或。实现了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::ops::BitXor&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;lt;&lt;/code&gt;: 左移运算符。实现了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::ops::Shl&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&amp;gt;&lt;/code&gt;: 右移运算符。实现了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::ops::Shr&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// &amp;amp; | ^ &amp;lt;&amp;lt; &amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//0  (01 &amp;amp;&amp;amp; 10 -&amp;gt; 00)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//3  (01 || 10 -&amp;gt; 11)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//3  (01 != 10 -&amp;gt; 11)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//4  (左移 -&amp;gt; &apos;01&apos;+&apos;00&apos; -&amp;gt; 100)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//0  (右移 -&amp;gt; o̶1̶ -&amp;gt; 0)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;赋值运算符&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//2 + 5 = 7&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//7 - 2 = 5&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//5 * 5 = 25&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//25 / 2 = 12 not 12.5&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//12 % 5 = 2&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//10 &amp;amp;&amp;amp; 10 -&amp;gt; 10 -&amp;gt; 2&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//010 || 101 -&amp;gt; 111 -&amp;gt; 7&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//111 != 010 -&amp;gt; 101 -&amp;gt; 5&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//&apos;101&apos;+&apos;0&apos; -&amp;gt; 1010 -&amp;gt; 10&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//101̶0̶ -&amp;gt; 10 -&amp;gt; 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;类型转换运算符: as&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//7.5&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;f64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//7.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;借用(Borrowing)与解引用(Dereference)操作符&lt;/li&gt;
&lt;/ul&gt;

Rust 引入了所有权(Ownership)的概念，所以在引用(Reference)的基础上衍生了借用(Borrowing)的概念，所有权概念不在这里展开。

简单而言，引用是为已存在变量创建一个别名；获取引用作为函数参数称为借用；解引用是与引用相反的动作，目的是返回引用指向的变量本身。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// 引用/借用： &amp;amp; &amp;amp;mut&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;calculate_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The length of &apos;{}&apos; is {}.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// The length of &apos;hello&apos; is 5.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;calculate_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;usize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 获取引用作为函数参数称为借用&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// 解引用： *&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 获取v的第2个元素的可变引用，并通过解引用修改该元素的值。&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;third&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.get_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.unwrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;third&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;v={:?}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// v=[1, 2, 53, 4, 5]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;26-流程控制&quot;&gt;2.6 流程控制&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;if - else if - else&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Small&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Medium&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Large&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 条件块中有返回值时，类型需要一致，可替代C语言的三目运算符&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_below_eighteen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;match&lt;/li&gt;
&lt;/ul&gt;

可替代C语言的switch case。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tshirt_width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tshirt_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tshirt_width&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;S&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// check 16&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;M&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// check 17 and 18&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;19&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;21&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;L&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// check from 19 to 21 (19,20,21)&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;22&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;XL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Not Available&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tshirt_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// L&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt;表示匹配剩下的任意情况。

match 的一些其他用法：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;正确&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;

    &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;3 或 4 或 5 或 6&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;

    &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;14..20&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ... 表示一个范围，可以是数字， `1 ... 10` 也可以是字母 `&apos;a&apos; ... &apos;z&apos;`&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;不正确&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;y={}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;

    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x={}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 配合 if 使用&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;14..20&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;不正确&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 后置套件&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;yes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;no&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 绑定变量&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;正确&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;

    &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;3 或 4 或 5 或 6&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;不正确&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;while&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Current value : {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Rust不支持++/--自增自减语法&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;loop&lt;/li&gt;
&lt;/ul&gt;

相当于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;while true&lt;/code&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Skip Value : {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Break At : {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Current Value : {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Skip Value : 0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Current Value : 1&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Break At : 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;for&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//(a = 0; a &amp;lt;10; a++)&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Current value : {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;&apos;outer_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//set label outer_for&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;&apos;inner_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Current Value : [{}][{}]&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&apos;outer_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 结束外层循环&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Mark&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Larry&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Bill&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Steve&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.iter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Current Person : {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在 for 表达式中的break ‘outer_for，loop 和 while 也有相同的使用方式。

&lt;h2 id=&quot;3-其他数据类型&quot;&gt;3. 其他数据类型&lt;/h2&gt;

&lt;h3 id=&quot;31-结构体struct&quot;&gt;3.1 结构体(struct)&lt;/h3&gt;

和元组(tuple)一样，结构体(struct)支持组合不同的数据类型，
但不同于元组，结构体需要给每一部分数据命名以标志其含义。
因而结构体比元组更加灵活，不依赖顺序来指定或访问实例中的值。

定义结构体

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sign_in_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;创建实例&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;someone@example.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;someusername123&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sign_in_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;修改某个字段的值&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;someone@example.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;someusername123&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sign_in_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;user1&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;anotheremail@example.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;变量与字段名同名的简写语法&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;build_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sign_in_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;元组结构体(tuple structs)&lt;/li&gt;
&lt;/ul&gt;

元组结构体有着结构体名称提供的含义，但没有具体的字段名。在参数个数较少时，无字段名称，仅靠下标也有很强的语义时，为每个字段命名就显得多余了。例如：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;black&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;32-枚举&quot;&gt;3.2 枚举&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;定义枚举&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IpAddrKind&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;V4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;V6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;使用枚举值&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;four&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IpAddrKind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;V4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ip_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IpAddrKind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;four&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;IpAddrKind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;V6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;枚举成员关联数据&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IpAddr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;V4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;V6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;home&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IpAddr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;V4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;127&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loopback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IpAddr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;V6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;::1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;更复杂的例子&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Message&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Quit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//  不关联数据&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Move&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 匿名结构体&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;ChangeColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;match 控制流&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Coin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Penny&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Nickel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Dime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Quarter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;value_in_cents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;coin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Coin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;coin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;Coin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Penny&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Lucky penny!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;Coin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Nickel&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;Coin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Dime&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;Coin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Quarter&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Option&lt;/li&gt;
&lt;/ul&gt;

Option是标准库中定义的一个非常重要的枚举类型。Option 类型应用广泛因为它编码了一个非常普遍的场景，
即一个值要么有值要么没值。对Rust而言，变量在使用前必须要赋予一个有效的值，
所以不存在空值(Null)，因此在使用任意类型的变量时，编译器确保它总是有一个有效的值，可以自信使用而无需做任何检查。如果一个值可能为空，需要显示地使用Option&lt;T&gt;来表示。&lt;/T&gt;

Option 的定义如下：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

Option&lt;T&gt;包含2个枚举项：&lt;/T&gt;

1) None，表明失败或没有值

2) Some(value)，元组结构体，封装了一个 T 类型的值 value

得益于Option，Rust 不允许一个可能存在空值的值，像一个正常的有效值那样工作，在编译时就能够检查出来。Rust显得更加安全，不用担心出现其他语言运行时才会出现的空指针异常的bug。例如：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Rust 没有空值(Null)，因此 i8只能被赋予一个有效值。&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// y 可能为空，需要显示地表示为枚举类型 Option&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

尝试将不可能出现无效值的 x:i8 与可能出现无效值的y: Option&lt;i8&gt; 相加时，编译器会报错：&lt;/i8&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;error[E0277]: the trait bound `i8: std::ops::Add&amp;lt;std::option::Option&amp;lt;i8&amp;gt;&amp;gt;` is
not satisfied
 --&amp;gt;
  |
5 |     let sum = x + y;
  |                 ^ no implementation for `i8 + std::option::Option&amp;lt;i8&amp;gt;`
  |
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

总结一下，如果一个值可能为空，必须使用枚举类型Option&lt;T&gt;，否则必须赋予有效值。而为了使用Option&lt;T&gt;，需要编写处理每个成员的代码，当T 为有效值时，才能够从 Some(T) 中取出 T 的值来使用，如果 T 为无效值，可以进行其他的处理，通常使用 match 来处理这种情况。&lt;/T&gt;&lt;/T&gt;

例如，当y为有效值时，返回x和y的和；为空值时，返回x。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;z1={}, z2={}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// z1=15, z2=10&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;if let 控制流&lt;/li&gt;
&lt;/ul&gt;

match 还有一种简单场景，可以简写为 if let。如下，y有值时，打印和，y无值时，啥事也不做。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x + y = {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// x + y = 15&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

简写为 if let，则是

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x + y = {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果只使用 if 呢？

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.is_some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.unwrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 获得 Some 中的 T 值。&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x + y = {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

if let 语句也可以包含 else。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x + y = {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;y is None&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 等价于&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x + y = {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;y is None&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;33-实现方法和接口impl--trait&quot;&gt;3.3 实现方法和接口(impl &amp;amp; trait)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;实现方法(impl)&lt;/li&gt;
&lt;/ul&gt;

Rust 通过关键字 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt; 在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enum&lt;/code&gt; 或者&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trait&lt;/code&gt; 上实现方法。
关联函数 (associated function) 的第一个参数通常为self参数，有3种变体：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self&lt;/code&gt;: 允许实现者移动和修改对象，对应的闭包特性为FnOnce。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;self&lt;/code&gt;: 既不允许实现者移动对象也不允许修改，对应的闭包特性为Fn。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;mut self&lt;/code&gt;: 允许实现者修改对象但不允许移动，对应的闭包特性为FnMut。&lt;/li&gt;
&lt;/ul&gt;

不含self参数的关联函数称为静态方法 (static method)。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;area&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.height&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;can_hold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Rectangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.height&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;square&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rect1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rect2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Rectangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;square&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;The area of the rectangle is {} square pixels.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rect1&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.area&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;The area of the rectangle is {} square pixels.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rect2&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.area&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

与结构体一样，枚举中的元素默认不能使用关系运算符进行比较 (如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!=&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;=&lt;/code&gt;)，
也不支持像&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;这样的双目运算符，需要自己实现，或者使用match进行匹配。

类似于 lua 里面的 metatables，可以通过实现一些借口函数来实现自定义结构体的运算：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.age&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.age&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

枚举默认也是私有的，如果使用pub使其变为公有，则它的元素也都是默认公有的。
这一点是与结构体不同的：即使结构体是公有的，它的域仍然是默认私有的。
这里的共有/私有仍然 是针对其定义所在的模块之外。此外，枚举和结构体也可以是递归的 (recursive)。

例如我们可以提供一个关联函数，它接受一个维度参数并且同时作为宽和高，
这样可以更轻松的创建一个正方形 Rectangle 而不必指定两次同样的值：

&lt;ul&gt;
  &lt;li&gt;实现接口(trait)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Summary&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;summarize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Summary&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;summarize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;format!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{width={}, height={}}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 接口也支持继承&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;full_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//Employee inherit from person trait&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;job_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Expat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;salary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;f32&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExpatEmployee&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Expat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 多继承，同时继承 Employee 和 Expat&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;additional_tax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;f64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

定义在特性中的方法称为默认方法 (default method)，可以被该特性的实现覆盖。 此外，特性之间也可以存在继承 (inheritance)：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// default method&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;We called bar.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// inheritance&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FooBar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foobar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Baz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Baz&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FooBar&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Baz&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foobar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;foobar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果两个不同特性的方法具有相同的名称，可以使用通用函数调用语法 (universal function call syntax)：

关于实现特性的几条限制：

&lt;ul&gt;
  &lt;li&gt;如果一个特性不在当前作用域内，它就不能被实现。&lt;/li&gt;
  &lt;li&gt;不管是特性还是impl，都只能在当前的包装箱内起作用。&lt;/li&gt;
  &lt;li&gt;
    带有特性约束的泛型函数使用单态化实现 (monomorphization)， 所以它是静态派分的 (statically dispatched)。
  &lt;/li&gt;
  &lt;li&gt;impl Trait&lt;/li&gt;
&lt;/ul&gt;

在版本1.26 开始，Rust提供了impl Trait的写法，作为和Scala 对等的既存型别(Existential Type)的写法。
在下面这个写法中，fn foo()将返回一个实作了Trait的trait。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//before&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Trait&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//after&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Trait&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

相较于1.25 版本以前的写法，新的写法会在很多场合中更有利于开发和执行效率。

impl Trait 的普遍用例

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Trait&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Trait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// implementation goes here&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Trait&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;f32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// implementation goes here&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

利用Box 会意味：即便回传的内容是固定的，但也会使用到动态内存分配。利用impl Trait 的写法可以避免便用Box。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//before&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Trait&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Trait&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//after&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Trait&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

其他受益的用例

闭包:

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// before&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// after&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

传参：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// before&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Trait&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// after&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Trait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;34-泛型generics&quot;&gt;3.4 泛型(Generics)&lt;/h3&gt;

当我们实现一个函数或者数据结构时，往往希望参数可以支持不同的类型，泛型可以解决这个问题。
声明参数类型时，换成大写的字母，例如字母 T，同时使用&lt;T&gt;告诉编译器 T 是泛型。&lt;/T&gt;

函数中使用泛型

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;largest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;largest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.iter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;largest&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;largest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;largest&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;vec!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;34&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;65&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;largest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The largest number is {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;char_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;vec!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;&apos;y&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;&apos;m&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;&apos;a&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;&apos;q&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;largest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;char_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The largest char is {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

结构体使用泛型

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;integer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

枚举使用泛型

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

Result 枚举有两个泛型类型，T 和 E。Result 有两个成员：Ok，它存放一个类型 T 的值，
而 Err 则存放一个类型 E 的值。这个定义使得 Result 枚举能很方便的表达任何可能成功（返回 T 类型的值）
也可能失败（返回 E 类型的值）的操作。回忆一下示例 9-3 中打开一个文件的场景：
当文件被成功打开 T 被放入了 std::fs::File 类型而当打开文件出现问题时 E 被放入了 std::io::Error 类型。

方法中使用泛型

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.x&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p.x = {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;35-常见集合-vec&quot;&gt;3.5 常见集合 Vec&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;新建&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// 空集合&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// let v = vec![1, 2, 3];  // 含初始值的集合，vec!是为方便初始化Vec提供的宏。&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;第三个元素 {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 3&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;第100个元素 {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// panic error&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;assert_eq!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;assert_eq!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

v.get(2) 和 &amp;amp;v[2] 都能获取到 Vec 的值，区别在于 &amp;amp;v[2] 返回的是该元素的引用，
引用一个不存在的位置，会引发错误。v.get(2) 返回的是枚举类型 Option&amp;lt;&amp;amp;T&amp;gt;。
v.get(2) 返回的是 Some(&amp;amp;3)，v.get(100) 返回的是 None。

&lt;ul&gt;
  &lt;li&gt;更新&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//删除最后一个元素&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;遍历&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;vec!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;57&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;vec!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;57&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;if let 控制流&lt;/li&gt;
&lt;/ul&gt;

如果我们想修改Vec中第2个元素的值呢？可以这么写：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;vec!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;third&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.get_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.unwrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;third&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;v={:?}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// v=[1, 2, 53, 4, 5]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

因为 v.get_mut() 的返回值是Option&lt;T&gt;枚举类型，那么可以使用if let来简化代码。&lt;/T&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;vec!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;third&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.get_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;third&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;v={:?}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// v=[1, 2, 53, 4, 5]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;while let 控制流&lt;/li&gt;
&lt;/ul&gt;

if let可以用于单个元素的场景，while let就适用于遍历的场景了。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;vec!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 依次打印 5 4 3 2 1&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

对于一个可变数组，Rust提供了一种简单的遍历形式—— for 循环。 我们可以获得一个数组的引用、可变引用、所有权。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;vec!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 获得引用&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 获得可变引用&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 获得所有权，注意此时Vec的属主将会被转移！！&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// @question 为什么说使用for容易造成嵌套循环&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

但是，这么写很容易出现多层for循环嵌套，因此，Vec提供了一个into_iter()方法，能显式地将自己转换成一个迭代器。

&lt;h3 id=&quot;36-常见集合-string&quot;&gt;3.6 常见集合 String&lt;/h3&gt;

Rust 的核心语言中只有一种字符串类型：str，字符串切片，它通常以被借用的形式出现，&amp;amp;str。这里提到的字符串，是字节的集合，外加一些常用方法实现。因为是集合，增持增删改，长度也可变。

&lt;ul&gt;
  &lt;li&gt;新建&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;initial contents&quot;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.to_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;更新&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.push_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 附加字符串&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;&apos;!&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 附加单字符&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;assert_eq!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;&apos;f&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 删除某个位置的字符&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello, &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;format&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tac&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;toe&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;format!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}-{}-{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// tic-tac-toe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;索引&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;assert_eq!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;&apos;h&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.chars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.nth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;遍历&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.chars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在Rust内部，String 是一个 Vec&lt;u8&gt; 的封装，
但是有些字符可能会占用超过2个字符，所以String不支持直接索引，如果需要索引需要使用 chars() 转换后再使用。&lt;/u8&gt;

&lt;h3 id=&quot;37-常见集合-hashmap&quot;&gt;3.7 常见集合 HashMap&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;新建&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;collections&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Blue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Yellow&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这里使用了use引入了HashMap结构体。

&lt;ul&gt;
  &lt;li&gt;访问&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;collections&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Blue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Yellow&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Blue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;score&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;team_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;更新&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;collections&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Blue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 10&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Blue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 25&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Blue 存在则不更新，不存在则更新，因此scores[&apos;Blue&apos;] 仍为 25&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Blue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.or_insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;4-错误处理&quot;&gt;4 错误处理&lt;/h2&gt;

&lt;h3 id=&quot;41-不可恢复错误-panic&quot;&gt;4.1 不可恢复错误 panic!&lt;/h3&gt;

Rust 有 panic!宏。当执行这个宏时，程序会打印出一个错误信息，
展开并清理栈数据，然后接着退出。出现这种场景，一般是出现了一些不知如何处理的场景。

&lt;ul&gt;
  &lt;li&gt;直接调用&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;panic!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;crash and burn&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行 cargo run 将打印出

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cargo run
Compiling tutu v0.1.0 (/xxx/demo/tutu)
    Finished dev [unoptimized + debuginfo] target(s) in 0.28s
     Running `target/debug/tutu`
thread &apos;main&apos; panicked at &apos;crash and burn&apos;, src/main.rs:2:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

最后2行包含了 panic!导致的报错信息，第1行是源码中 panic! 出现的位置 src/main.rs:2:5

&lt;ul&gt;
  &lt;li&gt;代码bug引起的错误&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;vec!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 越界&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

和之前一样，cargo run 的报错信息只有2行，缺少函数的调用栈，为了便于定位问题，
可以设置 RUST_BACKTRACE 环境变量来获得更多的调用栈信息，Rust 中称之为backtrace。
通过backtrace，可以看到执行到目前位置所有被调用的函数的列表。

例如执行 RUST_BACKTRACE=1 cargo run，这种方式的好处在于，环境变量只作用于当前命令。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ RUST_BACKTRACE=1 cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/tutu`
thread &apos;main&apos; panicked at &apos;index out of bounds: the len is 3 but the index is 99&apos;, /rustc/xxx/src/libcore/slice/mod.rs:2717:10
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.37/src/backtrace/libunwind.rs:88
  ...
  17: &amp;lt;alloc::vec::Vec&amp;lt;T&amp;gt; as core::ops::index::Index&amp;lt;I&amp;gt;&amp;gt;::index
             at /rustc/xxx/src/liballoc/vec.rs:1796
  18: tutu::main
             at src/main.rs:4
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

第一行的报错信息，说明了错误的原因，长度越界。紧接着打印出了函数调用栈，

src/main.rs:4 -&amp;gt; liballoc/vec.rs:1796 -&amp;gt; …

在windows下，可以执行 set RUST_BACKTRACE=1 &amp;amp;&amp;amp; cargo run。

&lt;ul&gt;
  &lt;li&gt;release&lt;/li&gt;
&lt;/ul&gt;

当出现 panic 时，程序默认会开始 展开（unwinding），
这意味着 Rust 会回溯栈并清理它遇到的每一个函数的数据，
不过这个回溯并清理的过程有很多工作。另一种选择是直接 终止（abort），
这会不清理数据就退出程序。那么程序所使用的内存需要由操作系统来清理。

release模式下，希望程序越小越好，可以在Cargo.toml中设置 panic 为 abort。

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;panic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;abort&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;42-可恢复错误-result&quot;&gt;4.2 可恢复错误 Result&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;处理 Result&lt;/li&gt;
&lt;/ul&gt;

有些错误，希望能够捕获并且做相应的处理，Rust 提供了 Result 机制来处理可恢复错误，
类似于其他语言中的try catch。

这是 Result&amp;lt;T, E&amp;gt;的定义

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

有些函数会返回Result，那怎么知道一个函数的返回对象是不是Result呢？很简单！

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当我们编译上面的代码时，将会报错。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;= note: expected type `u32`
            found type `std::result::Result&amp;lt;std::fs::File, std::io::Error&amp;gt;`
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

从报错信息可以看出，File::create 返回的是一个Result&amp;lt;fs::File. io::Error&amp;gt;对象，
如果没有异常，我们可以从Result::Ok&lt;T&gt;获取到文件句柄。&lt;/T&gt;

下面是一个完整的示例，创建 hello.txt 文件，并尝试写入 “Hello, world!”。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;prelude&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nd&quot;&gt;panic!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Problem create the file: {:?}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.write_all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;b&quot;Hello, world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(())&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nd&quot;&gt;panic!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Failed to write: {:?}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果执行成功，可以看到在工程根目录下，多出了 hello.txt 文件。

&lt;ul&gt;
  &lt;li&gt;unwrap 和 expect&lt;/li&gt;
&lt;/ul&gt;

Result 的处理有时太过于繁琐，Rust 提供了一种简洁的处理方式 unwrap 。
即，如果成功，直接返回 Result::Ok&lt;T&gt; 中的值，如果失败，则直接调用 !panic，程序结束。&lt;/T&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.unwrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 若成功，f则被赋值为文件句柄，失败则结束。&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

expect 是更人性化的处理方式，允许在调用!panic时，返回自定义的提示信息，对调试很有帮助。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Failed to open hello.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;返回 Result&lt;/li&gt;
&lt;/ul&gt;

我们可以实现类似于 File::open 这样的函数，让调用者能够自主绝对如何处理成功/失败的场景。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;read_username_from_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.read_to_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上面的函数如果成功，则返回 hello.txt 的文本字符串，失败，则返回 io::Error。

更简单的实现方式

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;read_username_from_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.read_to_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这种写法使用了?运算符向调用者返回错误。

作用是：如果 Result 的值是 Ok，则该表达式返回 Ok 中的值且程序继续执行。如果值是 Error ，
则将 Error 的值作为整个函数的返回值，好像使用了 return 关键字一样。这样写，逻辑更为清晰。

&lt;h2 id=&quot;5-包crate和模块&quot;&gt;5 包、crate和模块&lt;/h2&gt;

&lt;h3 id=&quot;51-包和-crate&quot;&gt;5.1 包和 crate&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.
├── Cargo.lock
├── Cargo.toml
├── benches
│   └── large-input.rs
├── examples
│   └── simple.rs
├── src
│   ├── bin
│   │   └── another_executable.rs
│   ├── lib.rs
│   └── main.rs
└── tests
    └── some-integration-tests.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

一个 Cargo 项目即一个包(Package)，一个包至少包含一个crate；
可以包含零个或多个二进制crate（binary crate），
但只能包含一个库crate(library crate)。 src/main.rs 是与包名同名的二进制 crate 的根，
其他的二进制 crate 的根放置在 src/bin 目录下； src/lib.rs 是与包名同名的库 crate 的根。

&lt;h3 id=&quot;52-模块&quot;&gt;5.2 模块&lt;/h3&gt;

模块 让我们可以将一个 crate 中的代码进行分组，以提高可读性与重用性。
即项是可以被外部代码使用的（public），还是作为一个内部实现的内容，
不能被外部代码使用（private）。

&lt;ul&gt;
  &lt;li&gt;声明模块&lt;/li&gt;
&lt;/ul&gt;

Rust中使用mod来声明模块，模块允许嵌套，可以使用模块名作为路径使用，例如：

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/main.rs&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;math&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;basic&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2 + 3 = {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;basic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2 * 3 = {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;basic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;引入作用域&lt;/li&gt;
&lt;/ul&gt;

使用use可以将路径引入作用域。

我们在 src/lib.rs 中声明一个模块，在 src/main.rs 中调用。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/lib.rs&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello, {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// pub 才能外部可见&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/main.rs&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tutu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;tutu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Jack&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Hello, Jack&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

路径的长度可以自由定义，也可以写成

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/main.rs&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tutu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Jack&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

src/main.rs 和 src/lib.rs 属于不同的 crate ，所以引入作用域时，需要带上包名 tutu 。

&lt;ul&gt;
  &lt;li&gt;分隔模块&lt;/li&gt;
&lt;/ul&gt;

在 src/lib.rs 中可以使用 mod 声明多个模块，但有时为了可读性，习惯将每个模块写在独立的文件中。

新建 src/greeting.rs，写入

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/greeting.rs&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello, {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在 src/lib.rs 可以这样使用，

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/lib.rs&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Tom&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

关键点就在于mod greeting;这一行，mod greeting后面没有具体实现，而是紧跟分号，则声明 greeting 的模块内容位于 src/greeting.rs 中。

其他crate，例如 src/main.rs 中的使用方式没有任何变化。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/main.rs&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tutu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Jack&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;6-测试&quot;&gt;6 测试&lt;/h2&gt;

&lt;h3 id=&quot;61-单元测试unit-tests&quot;&gt;6.1 单元测试(unit tests)&lt;/h3&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{} + {} = {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;#[test]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;it_works&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;assert_eq!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

单元测试非常简单，只需要在每一个测试用例前加上 #[test] 即可，通过 cargo test 执行用例。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cargo test
running 1 test
test it_works ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

更规范的写法是在每个源文件中，创建包含测试函数的 tests 模块，测试用例写在 tests 模块中，并使用 cfg(test) 标注模块。

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2 + 3 = {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;#[cfg(test)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tests&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;nd&quot;&gt;#[test]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;it_works&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;assert_eq!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

因为内部测试的代码和源码在同一文件，
因而需要使用 #[cfg(test)] 注解告诉 Rust 只在执行 cargo test 时才编译和运行测试代码，
因此，可以在构建库时节省时间，并减少编译文件产生的文件大小。

单元测试的好处在于，可以测试私有函数。如果在独立的目录，例如 tests 下做测试，
则只允许测试公开接口，即使用 pub 修饰后的模块和函数。

&lt;h3 id=&quot;62-集成测试integration-tests&quot;&gt;6.2 集成测试(integration tests)&lt;/h3&gt;

集成测试用例和源码位于不同的目录，因而源码中的模块和函数，
对于集成测试来说完全是外部的，因此，只能调用一部分库暴露的公共API。
Cargo 约定集成测试的代码位于项目根路径下的 tests 目录中，
Cargo 会将 tests 中的每一个文件当做一个 crate 来编译。

只有库 crate 才会向其他 crate 暴露可供调用的函数，
因此在 src/main.rs 中定义的函数不能够通过 extern crate 的方式导入，所以也不能够被集成测试。

src/main.rs 定义了 main 函数，即作为一个可执行(Executable)程序入口，
目的是独立运行，而非向其他 crate 提供可供调用的接口。

我们将 plus 函数移动到 src/lib.rs 中，新建 tests/test_lib.rs，最终的目录结构如下

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;├── Cargo.toml
├── src
│   └── lib.rs
│   └── main.rs
├── tests
    └── test_lib.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/lib.rs&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// plus 必须是公共API，才能被集成测试。&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/main.rs&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tutu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2 + 3 = {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tutu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// tests/test_lib.rs&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tutu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;#[test]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;it_works&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;assert_eq!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tutu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

运行 cargo test，将输出

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;running 1 test
test it_adds_two ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;7-生命周期&quot;&gt;7 生命周期&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;借用不改变内存的所有者（Owner），借用只是对源内存的临时引用。&lt;/li&gt;
  &lt;li&gt;在借用周期内，借用方可以读写这块内存，所有者被禁止读写内存；且所有者保证在有“借用”存在的情况下，不会释放或转移内存。&lt;/li&gt;
  &lt;li&gt;失去所有权的变量不可以被借用（访问）。&lt;/li&gt;
  &lt;li&gt;在租借期内，内存所有者保证不会释放/转移/可变租借这块内存，但如果是在非可变租借的情况下，所有者是允许继续非可变租借出去的。&lt;/li&gt;
  &lt;li&gt;借用周期满后，所有者收回读写权限&lt;/li&gt;
  &lt;li&gt;借用周期小于被借用者（所有者）的生命周期。&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 01 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/start-to-learn-rust/</link>
        <guid isPermaLink="true">https://wsdjeg.net/start-to-learn-rust/</guid>
        
        <category>rust</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>从 Vim 切换至 SpaceVim 的细节</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#准备工作&quot; id=&quot;markdown-toc-准备工作&quot;&gt;准备工作&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#迁移成本&quot; id=&quot;markdown-toc-迁移成本&quot;&gt;迁移成本&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;准备工作&quot;&gt;准备工作&lt;/h2&gt;

在切换至 SpaceVim 之前，需要先简单了解下以下几点：

&lt;ol&gt;
  &lt;li&gt;什么是 SpaceVim？&lt;/li&gt;
&lt;/ol&gt;

SpaceVim 是一套社区驱动的模块化 Vim 配置文件，因此还是需要安装 Vim 或者 Neovim。
建议使用 Neovim，因为 Neovim 的一些功能（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+py&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+py3&lt;/code&gt;）扩展以及内置的 API 更加容易使用。

&lt;ol&gt;
  &lt;li&gt;如何安装 SpaceVim？&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;迁移成本&quot;&gt;迁移成本&lt;/h2&gt;

相信这个是大多数 Vim 老用户顾虑和担心的事情，担心需要改变按键习惯，担心改变配置习惯。

&lt;ol&gt;
  &lt;li&gt;按键习惯&lt;/li&gt;
&lt;/ol&gt;

SpaceVim 内置的快捷键都是以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPC&lt;/code&gt; 为前缀键，不占用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Leader&lt;/code&gt; 键，这就意味着原先的一些
以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Leader&lt;/code&gt; 为前缀的快捷键，可以无缝迁移过来。

&lt;ol&gt;
  &lt;li&gt;配置习惯&lt;/li&gt;
&lt;/ol&gt;

同样是可以支持书写 Vim Script，只不过书写的位置不一样。原先可以在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.vimrc&lt;/code&gt; 这个文件内
书写 Vim Script，在 SpaceVim 内引入了一个新的概念，启动函数，这是一个当 SpaceVim 启动
时候会被调用的函数，可以将 Vim 脚本写在这个函数内，比如：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; myspacevim#init&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:focus_was_lost&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;notitle&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Thu, 20 Feb 2020 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/from-vim-to-spacevim-tips/</link>
        <guid isPermaLink="true">https://wsdjeg.net/from-vim-to-spacevim-tips/</guid>
        
        <category>spacevim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>SpaceVim 下的异步任务系统</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#配置文件&quot; id=&quot;markdown-toc-配置文件&quot;&gt;配置文件&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#基本使用&quot; id=&quot;markdown-toc-基本使用&quot;&gt;基本使用&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#进阶使用&quot; id=&quot;markdown-toc-进阶使用&quot;&gt;进阶使用&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

项目的构建、打包、测试通需要调用一些外部命令，比如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ant&lt;/code&gt;等，SpaceVim 内置一个任务管理系统，通过分析项目的任务配置文件，获取相关命令，并且异步执行，同时根据配置按照需求展示运行结果。

&lt;h2 id=&quot;配置文件&quot;&gt;配置文件&lt;/h2&gt;

配置文件支持全局配置文件以及项目局部配置文件，分别为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.SpaceVim.d/tasks.toml&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.SpaceVim.d/tasks.toml&lt;/code&gt;，局部配置文件具有更高的优先权限。

&lt;h3 id=&quot;基本使用&quot;&gt;基本使用&lt;/h3&gt;

以下为一个简单的 hello world 示例：

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my-first-task&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;echo&apos;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;hello world&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

添加以上内容至 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.SpaceVim.d/tasks.toml&lt;/code&gt;后，在SpaceVim内按下&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPC p t r&lt;/code&gt;快捷键，就会弹出如下界面：

&lt;img src=&quot;https://user-gold-cdn.xitu.io/2020/2/15/17046b77705d8292?w=679&amp;amp;h=84&amp;amp;f=png&amp;amp;s=8165&quot; alt=&quot;&quot; /&gt;

可以使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k&lt;/code&gt;按键进行上下选择，回车键执行，也可以按下任务名称前面的序号直接执行。执行效果如下：

&lt;img src=&quot;https://user-gold-cdn.xitu.io/2020/2/15/17046b920794243c?w=746&amp;amp;h=227&amp;amp;f=png&amp;amp;s=9599&quot; alt=&quot;&quot; /&gt;

&lt;h3 id=&quot;进阶使用&quot;&gt;进阶使用&lt;/h3&gt;

对于一些复杂的任务，可以使用预定义的一些变量，来简化配置文件，比如，在一个简单的C项目里：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[in]: e:/ctest/                         
  ▶ bin/                                    
  ▼ src/                                    
        main.c                                
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

编译一个简单的编译当前C文件&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/main.c&lt;/code&gt;至&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bin/&lt;/code&gt;目录，以及调用编译后的可以执行文件运行：

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file-build&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;gcc $(file) -o $(workspaceFolder)/bin/$(workspaceFolderBasename)&apos;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file-run&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(workspaceFolder)/bin/$(workspaceFolderBasename)&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
上面的配置文件里涉及到的变量分别是：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;变量名&lt;/th&gt;
      &lt;th&gt;值&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(file)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e:/ctest/src/main.c&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(workspaceFolder)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e:/ctest&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(workspaceFolderBasename)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctest&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  SpaceVim 中文官网: https://spacevim.org/cn/

  中文 Gitter 聊天室：https://gitter.im/SpaceVim/cn
&lt;/blockquote&gt;
</description>
        <pubDate>Fri, 14 Feb 2020 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/tasks-support-in-spacevim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/tasks-support-in-spacevim/</guid>
        
        <category>spacevim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>心型脂肪酸结合蛋白（H-FABP）检测的临床意义</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#什么是-h-fabp&quot; id=&quot;markdown-toc-什么是-h-fabp&quot;&gt;什么是 H-FABP？&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#与传统心肌标志物比较&quot; id=&quot;markdown-toc-与传统心肌标志物比较&quot;&gt;与传统心肌标志物比较&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#h-fabp-测定的临床应用&quot; id=&quot;markdown-toc-h-fabp-测定的临床应用&quot;&gt;H-FABP 测定的临床应用&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#急性冠脉综合征的预后价值&quot; id=&quot;markdown-toc-急性冠脉综合征的预后价值&quot;&gt;急性冠脉综合征的预后价值&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#h-fabp-与其他项目联合检查&quot; id=&quot;markdown-toc-h-fabp-与其他项目联合检查&quot;&gt;H-FABP 与其他项目联合检查&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  冠心病急性心肌梗死（AMI）是世界范围内严重威胁人类生命的疾病，
早期诊断急性心肌梗死对挽救病人生命非常重要。近年来，
人们提出心肌型脂肪酸结合蛋白（H-FABP）可以作为早期诊断急性心肌梗死的心肌标志物。
H-FABP 是一种低分子量胞浆蛋白，在心肌细胞中含量丰富，由于分子量较小，
在急性心肌梗死后 1.3 ～ 3 小时内血浆浓度开始升高。国外一些临床研究已经证实，
H-FABP 早期诊断急性心肌梗死较肌红蛋白有更好的特异性和敏感性，尤其在 AMI 早期 3 小时内有更好的诊断价值。
&lt;/blockquote&gt;

&lt;h2 id=&quot;什么是-h-fabp&quot;&gt;什么是 H-FABP？&lt;/h2&gt;

脂肪酸结合蛋白（FABPs）是一种小的胞质蛋白，在心脏和肝脏等具有活跃脂肪酸代谢的组织中大量表达（Viswanathan 等人 2012），
其主要功能是促进细胞内长链脂肪酸转运。9 种不同类型的 FABPs 家族已被确定，其中心脏型 FABP（H-FABP）是最为广泛研究的，
主要是由于在心肌细胞中发现的丰富。

它们的低分子量和细胞质位置的结合意味着 h-fabp 蛋白在急性心肌梗死（AMI）后最早被释放进入血液：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;生物标志物&lt;/th&gt;
      &lt;th&gt;分子量 (kDa)&lt;/th&gt;
      &lt;th&gt;初始检测时间&lt;/th&gt;
      &lt;th&gt;到达峰值&lt;/th&gt;
      &lt;th&gt;回到正常值&lt;/th&gt;
      &lt;th&gt;备注&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;H-FABP&lt;/td&gt;
      &lt;td&gt;15kDa&lt;/td&gt;
      &lt;td&gt;30 分钟&lt;/td&gt;
      &lt;td&gt;6-12 小时&lt;/td&gt;
      &lt;td&gt;24 小时&lt;/td&gt;
      &lt;td&gt;Early rise specificity&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Myoglobin&lt;/td&gt;
      &lt;td&gt;17kDa&lt;/td&gt;
      &lt;td&gt;1-3 小时&lt;/td&gt;
      &lt;td&gt;5-8 小时&lt;/td&gt;
      &lt;td&gt;16-24 小时&lt;/td&gt;
      &lt;td&gt;Early rise Low specificity&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Troponin I (TnI)&lt;/td&gt;
      &lt;td&gt;22kDa&lt;/td&gt;
      &lt;td&gt;3-6 小时&lt;/td&gt;
      &lt;td&gt;14-18 小时&lt;/td&gt;
      &lt;td&gt;5-10 天&lt;/td&gt;
      &lt;td&gt;Late rise High specificity&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Troponin T (TnT)&lt;/td&gt;
      &lt;td&gt;33kDa&lt;/td&gt;
      &lt;td&gt;3-6 小时&lt;/td&gt;
      &lt;td&gt;10-48 小时&lt;/td&gt;
      &lt;td&gt;10-15 天&lt;/td&gt;
      &lt;td&gt;Late rise High specificity&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CK-MB&lt;/td&gt;
      &lt;td&gt;86kDa&lt;/td&gt;
      &lt;td&gt;3-8 小时&lt;/td&gt;
      &lt;td&gt;9-24 小时&lt;/td&gt;
      &lt;td&gt;48-72 小时&lt;/td&gt;
      &lt;td&gt;Late rise High specificity&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;与传统心肌标志物比较&quot;&gt;与传统心肌标志物比较&lt;/h2&gt;

与传统的心肌标志物相比较，心型脂肪酸结合蛋白在早期诊断急性心肌梗死具有更好的特异性和敏感性。

&lt;h2 id=&quot;h-fabp-测定的临床应用&quot;&gt;H-FABP 测定的临床应用&lt;/h2&gt;

早期诊断急性心肌梗死：H-FABP 血浆释放特点与肌红蛋白相同，但 HFABP 在心肌细胞内的含量高于 Mb，而在血浆内的含量远低于 Mb。因此，当心肌损伤后，血浆 HFABP 迅速升高超正常上限，比 Mb 和肌钙蛋白来得快，因而更有诊断价值。近年来众多研究表明血清 H-FABP 能识别超急期急性心肌梗死，特别是胸痛发病 6 h 内的患者，对决定是否住院、冠状动脉造影、介入治疗有很大帮助。

评估心肌梗死面积：Wodzig 等测定 20 例 AMI 患者的 H-FABP、Mb、肌酸激酶同工酶(CK-MB)、羟丁酸脱氢酶(HBDH)，用 H-FABP 或 Mb 曲线，与用 CK-MB 或 HBDH 评估梗死面积具有较好的一致性。H-FABP 或 Mb 可用评估肾功能正常 AMI 患者发病 24 h 内的梗死面积。

评估再灌注损伤：58 例 AMI 患者行溶栓治疗，溶栓后 90min 行冠状动脉造影，溶栓前、溶栓后 60、90 min 和 180 min 分别测定 H-FABP 和 Mb 浓度。溶栓后相关血管开通者 H-FABP 和 Mb 明显高于未开通者。研究者认为: H-FABP、Mb 可作为再灌注指标，结合梗死面积分析，灵敏度和特异性可进一步提高。

评估心力衰竭严重程度与预后：Setsuta 等测定 103 例慢性心衰患者 H-FABP 及 cTnI，发现 cTnI≥0. 01μg /L 而且 H-FABP≥4.5μg/L 者心血管事件(死亡、病情加重再入院)发生率高于其它患者，提示 H-FABP 联合 cTnI 能独立预测心血管事件。

预测急性冠状动脉综合征心血管事件：在 ACS 发病早期的几小时内，筛选出可能发生心脏事件的高危患者很重要。最近已有报导血浆 H-FABP 浓度升高与心血管事件发生率及心血管死亡有关。Viswanathan 等入选 955 例怀疑 ACS 而肌钙蛋白阴性的患者(除外 ST 抬高性心肌梗死及新发左束支传导阻滞患者) ，于症状发生后 12 ～ 24h 检测 H-FABP，平均随访 18 个月后，H-FABP 浓度＞ 6.48 mg/L 者不良事件显著增加，提示 H-FABP 能独立预测中低危胸痛患者的心血管事件。

区分心肌或骨骼肌损伤：H-FABP 主要来自心肌，少部分来自骨骼肌。心脏电除颤、器官衰竭、手术后、强体力活动如跑步、划船，骨骼肌受损伤，也会引起血中 H-FABP 浓度升高。Mb/H-FABP 比值可用于鉴别心肌损伤(比值=2 ～ 10)和骨骼肌损伤(比值=20 ～ 70)。AMI 患者，血浆 Mb/H-FABP 比值为 0 ～ 5。

&lt;h3 id=&quot;急性冠脉综合征的预后价值&quot;&gt;急性冠脉综合征的预后价值&lt;/h3&gt;

除了对急性冠脉综合征有重要的诊断价值外，H-FABP 在这些患者的长期预后中也显示出巨大的价值，
即使与高灵敏度肌钙蛋白测定相比也是如此。

Kilcullen（JACC 2007）在 2007 年美国心脏病学会杂志上发表了一项前瞻性观察研究的详细资料，
详细介绍了在英国 11 家医院中 1448 名确诊急性冠脉综合征患者的队列。
患者在 ACS 症状出现 12-24 小时后，从单个血液样本中测量肌钙蛋白 I 和 H-Fabp。
随访 1 年后，发现 H-Fabp 浓度的升高对急性冠脉综合征后的死亡率具有很强的预测作用，
H-Fabp 能够在整个 TNI 浓度范围内识别高危患者。
6 个月时 h-fabp 和肌钙蛋白 I 均为阴性的患者死亡率为 0%，
因此被认为是非常低的风险。
然而，与 H-Fabp 阴性的患者相比，H-Fabp 阳性和肌钙蛋白阴性的患者在 1 年后死亡的风险明显较高。

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/63637793-9a332700-c6b3-11e9-9d54-c18e4ee81878.jpg&quot; alt=&quot;pg11&quot; /&gt;

&lt;blockquote&gt;
  Fig 5: Kaplan-Meier mortality curves for patients with either TnI≤0.06 μg/l (unstable angina) or TnI&amp;gt;0.06 μg/l (MI inclusive of STEMI/BBBMI) according to the H-FABP cut-off value of 5.8μg/l.
&lt;/blockquote&gt;

这些患者接受了 6 年的随访，除了肌钙蛋白阴性、H-Fabp 阳性的患者组在 6 年后死亡率最高（Pearson 等人，20109）。H-Fabp 不仅是一个独立的预后标志物，而且可以识别被认为是肌钙蛋白阴性的高危患者。

&lt;h2 id=&quot;h-fabp-与其他项目联合检查&quot;&gt;H-FABP 与其他项目联合检查&lt;/h2&gt;

下图为不同心肌标志物组合检查对于 AMI 症状出现时间的敏感性，由图中可以看出心型脂肪酸结合蛋白和肌钙蛋白 I 联合检查具有更高的敏感性。

H-FABP、cTnI 联合诊断 ACS

有研究表明应用心型脂肪酸结合蛋白（H-FABP）与肌钙蛋白 Ⅰ（cTnI）联合诊断 ACS 研究发现，相比单纯的检测而言，能够提高检测的阳性率，同时对于检测准确性和诊断敏感性的提高具有重要价值，因此更加值得临床借鉴，意义在于通过联合检测提高诊断率，便于临床及时对患者进行准确的治疗，从而提高治疗效果，改善患者预后情况。

H-FABP、肌钙蛋白 I、超敏 C 反应泛白联合诊断 AMI

hs-CRP、H-FABP、cTnT  联合检测诊断 AMI 的特异度、阳性预测值均达到了 100.0%，同时敏感度、阴性预测值也较高,达到了 97.8%。这说明心型脂肪酸结合蛋白、肌钙蛋白 T、超敏 C 反应蛋白联合检测,对于诊断急性心肌梗死具有较高的阳性预测值和特异度,其能有效降低误诊率,值得推广应用。

&lt;blockquote&gt;
  参考文献：
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;《心型脂肪酸结合蛋白（H—FABP）与肌钙蛋白 I（cTnI）联合诊断 ACS 的价值》- 中西医结合心血管病电子杂志 2017 年 4 期&lt;/li&gt;
  &lt;li&gt;《Clinical Value of H-FABP》&lt;/li&gt;
  &lt;li&gt;《心型脂肪酸结合蛋白、肌钙蛋白 T、超敏 C 反应蛋白联合检测在急性心肌梗死中的价值》- 中国医药科学杂志 2014 年 10 月第 4 卷第 19 期&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Thu, 22 Aug 2019 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/significance-of-h-fabp/</link>
        <guid isPermaLink="true">https://wsdjeg.net/significance-of-h-fabp/</guid>
        
        <category>ivd</category>
        
        
        <category>工作资料</category>
        
      </item>
    
      <item>
        <title>右键使用 SpaceVim 打开文件</title>
        <description>我们知道，在 Linux 命令行里，可以使用 cd 命令切换到项目所在的目录，
此时启动 SpaceVim，会读取工程目录下的一些 SpaceVim 配置信息。
这样的好处有很多，假定我日常需要编辑 Java Python 和 c 语言项目，
那么在使用SpaceVim时不需要在用户配置里将所有的语言模块都启用了，
而是只需要在 Java 项目根目录创建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.SpaceVim.d/init.toml&lt;/code&gt; 文件，
在此文件里启用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lang#java&lt;/code&gt; 模块即可。同理，在 Python 项目根目录同样操作启用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lang#python&lt;/code&gt; 模块即可。

但是在 windows 系统下使用 neovim-qt 时，就不太方便了，为此，添加了这一功能，可以使用 windows 自身的文件管理器，定位到项目所在位置后使用右键打开 SpaceVim 并读取项目下的 SpaceVim 配置。

下面，我们来看看如何添加：

&lt;ol&gt;
  &lt;li&gt;按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Win + r&lt;/code&gt; 在运行弹窗理输入：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;regedit&lt;/code&gt; 回车，打开注册表编辑器：&lt;/li&gt;
&lt;/ol&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/62628353-b584ff00-b95d-11e9-95ec-10634e32baa3.jpg&quot; alt=&quot;1&quot; /&gt;

&lt;ol&gt;
  &lt;li&gt;定位到 HKEY_CLASSES_ROOT &amp;gt; * &amp;gt; shell :&lt;/li&gt;
&lt;/ol&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/62628350-b4ec6880-b95d-11e9-9b34-5dd6743875ed.jpg&quot; alt=&quot;2&quot; /&gt;

右键新建项，此时可以输入一个你需要看到的名字，比如 使用 SpaceVim 打开，
再在这个项里新建一个 command 项，修改其默认值为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;D:\Program Files\Neovim\bin\nvim-qt.exe&quot; -qwindowgeometry 1310x650+20+20 &quot;%1&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

最新版 Neovim 修改为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nvim --server \\.\pipe\nvim-pipe-123123123 --remote &quot;%1&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

需要在 Neovim 的配置文件里面增加：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pcall(function()
    vim.fn.serverstart([[\\.\pipe\nvim-pipe-123123123]])
end)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此时，就可以在右键中使用 neovim-qt 打开文件了，上面启动参数里指定了窗口位置和大小，可以自行调节。

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/62628347-b4ec6880-b95d-11e9-9eed-c928f9b91f0d.gif&quot; alt=&quot;3&quot; /&gt;
</description>
        <pubDate>Wed, 07 Aug 2019 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/open-with-spacevim-from-right-click-menu/</link>
        <guid isPermaLink="true">https://wsdjeg.net/open-with-spacevim-from-right-click-menu/</guid>
        
        <category>spacevim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>使用 Vim 管理待办事项</title>
        <description>&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#简介&quot; id=&quot;markdown-toc-简介&quot;&gt;简介&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#安装&quot; id=&quot;markdown-toc-安装&quot;&gt;安装&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;简介&quot;&gt;简介&lt;/h2&gt;

这一功能主要是方便检索源码中的待办事项。只需要在源码注释中加入相关标签即可，比如

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot; @todo Use new prolog plugin&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; call add(plugins, [&apos;wsdjeg/prolog-vim&apos;, { &apos;merged&apos; : 0}])&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;plugins&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/prolog.vim&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;merged&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/61044482-5342e800-a40b-11e9-9d6c-88cc20b06095.png&quot; alt=&quot;&quot; /&gt;

&lt;h2 id=&quot;安装&quot;&gt;安装&lt;/h2&gt;

vim-todo 这一插件分离自 SpaceVim，可以在 SpaceVim 中使用，当然也支持独立安装。
可以使用任意插件管理器，比如 dein 来安装 vim-todo：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; dein#&lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/vim-todo&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这一插件依赖于 Vim 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+job&lt;/code&gt; 特性，因此需要确保你的 Vim 版本满足要求，并且需要安装一个命令行工具 &lt;a href=&quot;https://github.com/jremmen/vim-ripgrep&quot;&gt;rg&lt;/a&gt;
</description>
        <pubDate>Tue, 06 Aug 2019 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/todo-manager-in-vim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/todo-manager-in-vim/</guid>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>如何学习并使用 SpaceVim</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#起因&quot; id=&quot;markdown-toc-起因&quot;&gt;起因&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

在 SpaceVim 的聊天室里，经常可以看到用户提问相类似的问题，或者说提问一些文档中已经写的很清楚的问题。
</description>
        <pubDate>Mon, 05 Aug 2019 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/the-way-to-learn-spacevim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/the-way-to-learn-spacevim/</guid>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>《波西米亚狂想曲》观后感</title>
        <description>好久没有去电影院看电影了。最近，在跟天天一起走访终端，正好今天抽空去看了一场电影《波西米亚狂想曲》。

每个人都会有自己热爱的东西、向往的东西。

再往后的日子里不断地去追寻，会遇到世间各种纷纷扰扰。

只期望能保持初心。

</description>
        <pubDate>Wed, 27 Mar 2019 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/movie-review-Bohemian-Rhapsody/</link>
        <guid isPermaLink="true">https://wsdjeg.net/movie-review-Bohemian-Rhapsody/</guid>
        
        <category>movie</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>降钙素原检测的临床意义</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#导读&quot; id=&quot;markdown-toc-导读&quot;&gt;导读&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#概念&quot; id=&quot;markdown-toc-概念&quot;&gt;概念&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#临床意义&quot; id=&quot;markdown-toc-临床意义&quot;&gt;临床意义&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#感染类&quot; id=&quot;markdown-toc-感染类&quot;&gt;感染类&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#非感染类&quot; id=&quot;markdown-toc-非感染类&quot;&gt;非感染类&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#pctil-6crp联合检查&quot; id=&quot;markdown-toc-pctil-6crp联合检查&quot;&gt;PCT、IL-6、CRP联合检查&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;导读&quot;&gt;导读&lt;/h2&gt;

PCT作为一种新的感染性炎性标志物目前已被广泛认可。
PCT对于细菌引起的感染有较高的灵敏度和特异性，
能帮助临床医生早期诊断患者是否存在或合并有细菌引起的感染，
鉴别诊断感染是由细菌所致还是病毒导致，
或其他原因引起的炎症反应有利于患者早期正确的治疗。

&lt;h2 id=&quot;概念&quot;&gt;概念&lt;/h2&gt;

降钙素原（procalcitonin，简称PCT）是一种由116个氨基酸组成的糖蛋白，
是降钙素（calcitonin，简称CT）的前体肽。
降钙素可被酶裂解为许多小的片断，最终形成氨基降钙素原、
成熟的降钙素和钙抑肽。正常情况下，PCT主要由甲状腺C细胞合成分泌，
游离形式存在于正常人血清中。在细菌感染时，肝脏的巨噬细胞和单核细胞、
肺及肠道组织的淋巴细胞及内分泌细胞，在内毒素、肿瘤坏死因子-α（TNF-α）
及白介素-6（IL-6）等作用下合成分泌大量的PCT，导致血清PCT水平显著升高。

&lt;h2 id=&quot;临床意义&quot;&gt;临床意义&lt;/h2&gt;

根据PCT水平及改变情况指导抗生素的使用，减少不必要的抗生素使用，
降低患者费用，减少过度使用抗生素所致的细菌耐药性增加及改变情况评估感染的严重程度和预测患者的预后。
PCT是一个非常有应用价值的诊断感染状态的微生物学指标，同时也可能是细菌感染的新的治疗途径。
目前导致PCT升高的疾病总的来说可以分为感染和非感染两大类：

&lt;h3 id=&quot;感染类&quot;&gt;感染类&lt;/h3&gt;

PCT在细菌感染引起的全身性炎症反应早期（2~3h）即可升高，感染后12~24h达到高峰，
PCT浓度与感染严重程度呈正相关，感染消失后恢复正常。因此对严重细菌感染的早期诊断、
判断病情严重程度、预后、评价抗感染疗效、指导抗菌药物应用等方面都具有较高的临床价值。

&lt;h3 id=&quot;非感染类&quot;&gt;非感染类&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;手术后&lt;/li&gt;
  &lt;li&gt;严重创伤&lt;/li&gt;
  &lt;li&gt;严重烧伤&lt;/li&gt;
  &lt;li&gt;持续性心源性休克&lt;/li&gt;
  &lt;li&gt;严重灌注不足，多器官功能衰竭，重症胰腺炎&lt;/li&gt;
  &lt;li&gt;严重肾功能不全&lt;/li&gt;
  &lt;li&gt;器官移植&lt;/li&gt;
  &lt;li&gt;严重肝硬化，或急慢性病毒性肝炎&lt;/li&gt;
  &lt;li&gt;新生儿出生最初几天&lt;/li&gt;
  &lt;li&gt;中暑&lt;/li&gt;
  &lt;li&gt;某些自身免疫性疾病&lt;/li&gt;
  &lt;li&gt;肿瘤晚期&lt;/li&gt;
  &lt;li&gt;横纹肌溶解症状&lt;/li&gt;
  &lt;li&gt;持续心肺复苏后&lt;/li&gt;
  &lt;li&gt;药物因素&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;pctil-6crp联合检查&quot;&gt;PCT、IL-6、CRP联合检查&lt;/h2&gt;

特别注意：没有任何一个生物标志物是绝对敏感又绝对特异的，
不能单凭某个生物标志物的改变来诊断疾病，只有结合、
参照患者的临床表现与其他实验室检查结果，才能做出正确的判断。

联合检查是未来的趋势：

1、《感染相关生物标志物临床意义解读专家共识》指出：“多个指标的联合检测将是未来的发展趋势，可提高对感染性疾病的早期诊断率和预后判断价值。”[1]
2、PCT、IL-6、CRP相比，IL-6的敏感性优于PCT和CRP，但它的特异性比PCT差，联检项目可以优势互补，各取所长。有研究显示，针对脓毒症患者联合检测PCT+IL-6+CRP、PCT+IL-6或PCT+CRP ，有助于临床识别早期脓毒症[3]（见表1）
表1 三种检测指标敏感性和特异性比较（%）

3、另一项研究PCT、CRP及 IL-6联合测定可以提高对细菌感染和病毒感染的鉴别效力，同时可有效的指导临床抗生素的使用、评估治疗效果[4]。
</description>
        <pubDate>Tue, 01 Jan 2019 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/significance-of-pct/</link>
        <guid isPermaLink="true">https://wsdjeg.net/significance-of-pct/</guid>
        
        <category>ivd</category>
        
        
        <category>工作资料</category>
        
      </item>
    
      <item>
        <title>再见了，网易博客</title>
        <description>&lt;img src=&quot;../images/163blog.png&quot; alt=&quot;&quot; /&gt;

用了很多年的网易博客有点舍不得，可惜后续不能再使用了，网易新推出的写作平台不是很感冒。

是时候说再见了。
</description>
        <pubDate>Wed, 12 Dec 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/goodbye-163-blog/</link>
        <guid isPermaLink="true">https://wsdjeg.net/goodbye-163-blog/</guid>
        
        <category>blog</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>Ruby 模块和包</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#require-语句&quot; id=&quot;markdown-toc-require-语句&quot;&gt;require 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#include-语句&quot; id=&quot;markdown-toc-include-语句&quot;&gt;include 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#mixins&quot; id=&quot;markdown-toc-mixins&quot;&gt;Mixins&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

模块（Module）是一种把方法、类和常量组合在一起的方式。模块（Module）为您提供了两大好处。

&lt;ul&gt;
  &lt;li&gt;模块提供了一个命名空间和避免名字冲突。&lt;/li&gt;
  &lt;li&gt;模块实现了 mixin 装置。&lt;/li&gt;
&lt;/ul&gt;

模块（Module）定义了一个命名空间，相当于一个沙盒，在里边您的方法和常量不会与其他地方的方法常量冲突。

模块类似与类，但有一下不同：

&lt;ul&gt;
  &lt;li&gt;模块不能实例化&lt;/li&gt;
  &lt;li&gt;模块没有子类&lt;/li&gt;
  &lt;li&gt;模块只能被另一个模块定义&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;module Identifier
   statement1
   statement2
   ...........
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

模块常量命名与类常量命名类似，以大写字母开头。方法定义看起来也相似：模块方法定义与类方法定义类似。

通过类方法，您可以在类方法名称前面放置模块名称和一个点号来调用模块方法，您可以使用模块名称和两个冒号来引用一个常量。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 定义在 trig.rb 文件中的模块&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Trig&lt;/span&gt;
   &lt;span class=&quot;no&quot;&gt;PI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.141592654&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Trig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;# ..&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Trig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;# ..&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

我们可以定义多个函数名称相同但是功能不同的模块：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 定义在 moral.rb 文件中的模块&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Moral&lt;/span&gt;
   &lt;span class=&quot;no&quot;&gt;VERY_BAD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
   &lt;span class=&quot;no&quot;&gt;BAD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Moral&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;badness&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

就像类方法，当您在模块中定义一个方法时，您可以指定在模块名称后跟着一个点号，点号后跟着方法名。

&lt;h4 id=&quot;require-语句&quot;&gt;require 语句&lt;/h4&gt;

require 语句类似于 C 和 C++ 中的 include 语句以及 Java 中的 import 语句。
如果一个第三方的程序想要使用任何已定义的模块，则可以简单地使用 Ruby require 语句来加载模块文件：

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;require filename
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在这里，文件扩展名 .rb 不是必需的。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;vg&quot;&gt;$LOAD_PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;.&apos;&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;trig.rb&apos;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;moral&apos;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Trig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Trig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;wrongdoing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Moral&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Moral&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;VERY_BAD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在这里，我们使用 $LOAD_PATH « ’.’ 让 Ruby 知道必须在当前目录中搜索被引用的文件。
如果您不想使用 $LOAD_PATH，那么您可以使用 require_relative 来从一个相对目录引用文件。

注意：在这里，文件包含相同的函数名称。所以，这会在引用调用程序时导致代码模糊，
但是模块避免了这种代码模糊，而且我们可以使用模块的名称调用适当的函数。

&lt;h4 id=&quot;include-语句&quot;&gt;include 语句&lt;/h4&gt;

您可以在类中嵌入模块。为了在类中嵌入模块，您可以在类中使用 include 语句：
语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;include modulename
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果模块是定义在一个单独的文件中，那么在嵌入模块之前使用 require 语句引用该文件时必需的。

实例

假设下面的模块写在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruby/support.rb&lt;/code&gt; 文件中。

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Week&lt;/span&gt;
   &lt;span class=&quot;no&quot;&gt;FIRST_DAY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Sunday&quot;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Week&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;weeks_in_month&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;You have four weeks in a month&quot;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Week&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;weeks_in_year&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;You have 52 weeks in a year&quot;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

现在，您可以在类中引用该模块，如下所示：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$LOAD_PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;./ruby&apos;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;support&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Decade&lt;/span&gt;
&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Week&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;no_of_yrs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;no_of_months&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Week&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FIRST_DAY&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;d1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Decade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Week&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FIRST_DAY&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Week&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;weeks_in_month&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Week&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;weeks_in_year&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;d1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;no_of_months&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这将产生以下结果：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/62424340-2c24c100-b700-11e9-9b10-6537ad594258.png&quot; alt=&quot;图片&quot; /&gt;

&lt;h4 id=&quot;mixins&quot;&gt;Mixins&lt;/h4&gt;

在阅读本节之前，您需要初步了解面向对象的概念。

当一个类可以从多个父类继承类的特性时，该类显示为多重继承。

Ruby 不直接支持多重继承，但是 Ruby 的模块（Module）有另一个神奇的功能。它几乎消除了多重继承的需要，提供了一种名为 mixin 的装置。

Mixins 向您提供了一种完美的为类添加功能的控制方式。但是，它们真正的强大在于当 mixin 中的代码开始与使用它的类中的代码交互时。

让我们看看下面的示例代码，深入了解 mixin：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;A&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;a1&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;a2&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;B&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;b1&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;b2&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Sample&lt;/span&gt;
&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;A&lt;/span&gt;
&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;B&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;s1&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;samp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Sample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;samp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;a1&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;samp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;a2&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;samp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;b1&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;samp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;b2&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;samp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;s1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

模块 A 由方法 a1 和 a2 组成。
模块 B 由方法 b1 和 b2 组成。
类 Sample 包含了模块 A 和 B。
类 Sample 可以访问所有四个方法，即 a1、a2、b1 和 b2。
因此，您可以看到类 Sample 继承了两个模块，您可以说类 Sample 使用了多重继承或 mixin 。
</description>
        <pubDate>Wed, 10 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/ruby-modules/</link>
        <guid isPermaLink="true">https://wsdjeg.net/ruby-modules/</guid>
        
        <category>ruby</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Ruby 代码块</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#yield-语句&quot; id=&quot;markdown-toc-yield-语句&quot;&gt;yield 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#块和方法&quot; id=&quot;markdown-toc-块和方法&quot;&gt;块和方法&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#begin-和-end-块&quot; id=&quot;markdown-toc-begin-和-end-块&quot;&gt;BEGIN 和 END 块&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

您已经知道 Ruby 如何定义方法以及您如何调用方法。类似地，Ruby 有一个块的概念。

&lt;ul&gt;
  &lt;li&gt;块由大量的代码组成。&lt;/li&gt;
  &lt;li&gt;您需要给块取个名称。&lt;/li&gt;
  &lt;li&gt;块中的代码总是包含在大括号 {} 内。&lt;/li&gt;
  &lt;li&gt;块总是从与其具有相同名称的函数调用。这意味着如果您的块名称为 test，那么您要使用函数 test 来调用这个块。&lt;/li&gt;
  &lt;li&gt;您可以使用 yield 语句来调用块。&lt;/li&gt;
&lt;/ul&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;block_name{
   statement1
   statement2
   ..........
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在这里，您将学到如何使用一个简单的 yield 语句来调用块。
您也将学到如何使用带有参数的 yield 语句来调用块。
在实例中，您将看到这两种类型的 yield 语句。

&lt;h4 id=&quot;yield-语句&quot;&gt;yield 语句&lt;/h4&gt;

让我们看一个 yield 语句的实例：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;在 test 方法内&quot;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;你又回到了 test 方法内&quot;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;你在块内&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/62424097-c4b94200-b6fc-11e9-8659-c24b90969262.png&quot; alt=&quot;图片&quot; /&gt;

您也可以传递带有参数的 yield 语句。下面是一个实例：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;在 test 方法内&quot;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;你在块 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; 内&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在这里，yield 语句后跟着参数。您甚至可以传递多个参数。在块中，您可以在两个竖线之间放置一个变量来接受参数。
因此，在上面的代码中，yield 5 语句向 test 块传递值 5 作为参数。

现在，看下面的语句：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;test {|i| puts &quot;你在块 #{i} 内&quot;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在这里，值 5 会在变量 i 中收到。现在，观察下面的 puts 语句：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;puts &quot;你在块 #{i} 内&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这个 puts 语句的输出是：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;你在块 5 内
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果您想要传递多个参数，那么 yield 语句如下所示：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yield a, b
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此时，块如下所示：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;test {|a, b| statement}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

参数使用逗号分隔。

&lt;h4 id=&quot;块和方法&quot;&gt;块和方法&lt;/h4&gt;

您已经看到块和方法之间是如何相互关联的。您通常使用 yield 语句从与其具有相同名称的方法调用块。因此，代码如下所示：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello world&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

本实例是实现块的最简单的方式。您使用 yield 语句调用 test 块。

但是如果方法的最后一个参数前带有 &amp;amp;，那么您可以向该方法传递一个块，且这个块可被赋给最后一个参数。如果 * 和 &amp;amp; 同时出现在参数列表中，&amp;amp; 应放在后面。

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello World!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;begin-和-end-块&quot;&gt;BEGIN 和 END 块&lt;/h4&gt;

每个 Ruby 源文件可以声明当文件被加载时要运行的代码块（BEGIN 块），以及程序完成执行后要运行的代码块（END 块）。

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;BEGIN&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# BEGIN 代码块&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;BEGIN 代码块&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;END&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# END 代码块&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;END 代码块&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# MAIN 代码块&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;MAIN 代码块&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

一个程序可以包含多个 BEGIN 和 END 块。BEGIN 块按照它们出现的顺序执行。END 块按照它们出现的相反顺序执行。当执行时，上面的程序产生产生以下结果：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;BEGIN 代码块
MAIN 代码块
END 代码块
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Thu, 04 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/ruby-block/</link>
        <guid isPermaLink="true">https://wsdjeg.net/ruby-block/</guid>
        
        <category>ruby</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Ruby 函数</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#从方法返回值&quot; id=&quot;markdown-toc-从方法返回值&quot;&gt;从方法返回值&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#return-语句&quot; id=&quot;markdown-toc-return-语句&quot;&gt;return 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#可变数量的参数&quot; id=&quot;markdown-toc-可变数量的参数&quot;&gt;可变数量的参数&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#类方法&quot; id=&quot;markdown-toc-类方法&quot;&gt;类方法&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#alias-语句&quot; id=&quot;markdown-toc-alias-语句&quot;&gt;alias 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#undef-语句&quot; id=&quot;markdown-toc-undef-语句&quot;&gt;undef 语句&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

Ruby 方法与其他编程语言中的函数类似。Ruby 方法用于捆绑一个或多个重复的语句到一个单元中。

方法名应以小写字母开头。如果您以大写字母作为方法名的开头，Ruby 可能会把它当作常量，从而导致不正确地解析调用。

方法应在调用之前定义，否则 Ruby 会产生未定义的方法调用异常。

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def method_name [( [arg [= default]]...[, * arg [, &amp;amp;expr ]])]
   expr..
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

所以，您可以定义一个简单的方法，如下所示：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def method_name
   expr..
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

您可以定义一个接受参数的方法，如下所示：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def method_name (var1, var2)
   expr..
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

您可以为参数设置默认值，如果方法调用时未传递必需的参数则使用默认值：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def method_name (var1=value1, var2=value2)
   expr..
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当您要调用方法时，只需要使用方法名即可，如下所示：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;method_name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

但是，当您调用带参数的方法时，您在写方法名时还要带上参数，例如：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;method_name 25, 30
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

使用带参数方法最大的缺点是调用方法时需要记住参数个数。例如，
如果您向一个接受三个参数的方法只传递了两个参数，Ruby 会显示错误。

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Ruby&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Perl&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;编程语言为 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;编程语言为 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a2&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;C&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;C++&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;从方法返回值&quot;&gt;从方法返回值&lt;/h4&gt;

Ruby 中的每个方法默认都会返回一个值。这个返回的值是最后一个语句的值。例如：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tvar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tvar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在调用这个方法时，将返回最后一个声明的变量 k。

&lt;h4 id=&quot;return-语句&quot;&gt;return 语句&lt;/h4&gt;

Ruby 中的 return 语句用于从 Ruby 方法中返回一个或多个值。
语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;return [expr[&apos;,&apos; expr...]]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果给出超过两个的表达式，包含这些值的数组将是返回值。如果未给出表达式，nil 将是返回值。

实例

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;return

或

return 12

或

return 1,2,3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

看看下面的实例：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;可变数量的参数&quot;&gt;可变数量的参数&lt;/h4&gt;

假设您声明了一个带有两个参数的方法，当您调用该方法时，您同时还需要传递两个参数。

但是，Ruby 允许您声明参数数量可变的方法。让我们看看下面的实例：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;The number of parameters is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;The parameters are &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Zara&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;6&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;F&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Mac&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;36&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;M&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;MCA&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在这段代码中，您已经声明了一个方法 sample，接受一个参数 test。但是，这个参数是一个变量参数。这意味着参数可以带有不同数量的变量。所以上面的代码将产生下面的结果：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/62423960-b23e0900-b6fa-11e9-84ab-25ddf6281a22.png&quot; alt=&quot;图片&quot; /&gt;

&lt;h4 id=&quot;类方法&quot;&gt;类方法&lt;/h4&gt;

当方法定义在类定义外部时，方法默认标记为 private。另一方面，定义在类定义中的方法默认标记为 public。方法默认的可见性和 private 标记可通过模块（Module）的 public 或 private 改变。

当你想要访问类的方法时，您首先需要实例化类。然后，使用对象，您可以访问类的任何成员。

Ruby 提供了一种不用实例化类即可访问方法的方式。让我们看看如何声明并访问类方法：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Accounts&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;reading_charge&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Accounts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;return_date&lt;/span&gt;
       &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;2019&quot;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 我们已经知道方法 return_date 是如何声明的。&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 它是通过在类名后跟着一个点号，点号后跟着方法名来声明的。&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 您可以直接访问类方法，如下所示：&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Accounts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;return_date&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如需访问该方法，您不需要创建类 Accounts 的对象。

&lt;h4 id=&quot;alias-语句&quot;&gt;alias 语句&lt;/h4&gt;

这个语句用于为方法或全局变量起别名。别名不能在方法主体内定义。即使方法被重写，方法的别名也保持方法的当前定义。

为编号的全局变量（$1, $2,…）起别名是被禁止的。重写内置的全局变量可能会导致严重的问题。

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alias 方法名 方法名
alias 全局变量 全局变量
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

实例

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alias foo bar
alias $MATCH $&amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在这里，我们已经为 bar 定义了别名为 foo，为 $&amp;amp; 定义了别名为 $MATCH。

&lt;h4 id=&quot;undef-语句&quot;&gt;undef 语句&lt;/h4&gt;

这个语句用于取消方法定义。undef 不能出现在方法主体内。

通过使用 undef 和 alias，类的接口可以从父类独立修改，但请注意，在自身内部方法调用时，它可能会破坏程序。

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;undef 方法名
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

实例

下面的实例取消名为 bar 的方法定义：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;undef bar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Sun, 30 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/ruby-functions/</link>
        <guid isPermaLink="true">https://wsdjeg.net/ruby-functions/</guid>
        
        <category>ruby</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Ruby 循环</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#while-语句&quot; id=&quot;markdown-toc-while-语句&quot;&gt;while 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#while-修饰符&quot; id=&quot;markdown-toc-while-修饰符&quot;&gt;while 修饰符&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#until-语句&quot; id=&quot;markdown-toc-until-语句&quot;&gt;until 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#until-修饰符&quot; id=&quot;markdown-toc-until-修饰符&quot;&gt;until 修饰符&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#for-语句&quot; id=&quot;markdown-toc-for-语句&quot;&gt;for 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#break-语句&quot; id=&quot;markdown-toc-break-语句&quot;&gt;break 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#next-语句&quot; id=&quot;markdown-toc-next-语句&quot;&gt;next 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#redo-语句&quot; id=&quot;markdown-toc-redo-语句&quot;&gt;redo 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#retry-语句&quot; id=&quot;markdown-toc-retry-语句&quot;&gt;retry 语句&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

Ruby 中的循环用于执行相同的代码块若干次。

&lt;h2 id=&quot;while-语句&quot;&gt;while 语句&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;while conditional [do]
   code
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

或者

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;pre&amp;gt;
while conditional [:]
   code
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当 conditional 为真时，执行 code。

语法中 do 或 : 可以省略不写。但若要在一行内写出 while 式，则必须以 do 或 : 隔开条件式或程式区块。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;vg&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$num&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;在循环语句中 i = &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#$i&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;vg&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;while-修饰符&quot;&gt;while 修饰符&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;code while condition
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

或者

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;begin
  code
end while conditional
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当 conditional 为真时，执行 code。

如果 while 修饰符跟在一个没有 rescue 或 ensure 子句的 begin 语句后面，code 会在 conditional 判断之前执行一次。
实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;vg&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;在循环语句中 i = &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#$i&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;vg&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$num&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;until-语句&quot;&gt;until 语句&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;until conditional [do]
   code
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当 conditional 为假时，执行 code。

语法中 do 可以省略不写。但若要在一行内写出 until 式，则必须以 do 隔开条件式或程式区块。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;vg&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;until&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$num&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;在循环语句中 i = &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#$i&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;vg&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;until-修饰符&quot;&gt;until 修饰符&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;code until conditional
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

或者

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;begin
   code
end until conditional
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当 conditional 为假时，执行 code。

如果 until 修饰符跟在一个没有 rescue 或 ensure 子句的 begin 语句后面，code 会在 conditional 判断之前执行一次。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;vg&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;在循环语句中 i = &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#$i&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;vg&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;until&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$num&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;for-语句&quot;&gt;for 语句&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;for variable [, variable ...] in expression [do]
   code
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

针对 expression 中的每个元素分别执行一次 code。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;局部变量的值为 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在这里，我们已经定义了范围 0..5。语句 for i in 0..5 允许 i 的值从 0 到 5（包含 5）。

for…in 循环几乎是完全等价于：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(expression).each do |variable[, variable...]| code end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

但是，for 循环不会为局部变量创建一个新的作用域。

语法中 do 可以省略不写。但若要在一行内写出 for 式，则必须以 do 隔开条件式或程式区块。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;局部变量的值为 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;break-语句&quot;&gt;break 语句&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;break
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

终止最内部的循环。如果在块内调用，则终止相关块的方法（方法返回 nil）。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;局部变量的值为 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;next-语句&quot;&gt;next 语句&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;next
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

跳到最内部循环的下一个迭代。如果在块内调用，则终止块的执行（yield 或调用返回 nil）。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;next&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;局部变量的值为 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;redo-语句&quot;&gt;redo 语句&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;redo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

重新开始最内部循环的该次迭代，不检查循环条件。如果在块内调用，则重新开始 yield 或 call。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;局部变量的值为 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;redo&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这将产生以下结果，并会进入一个无限循环：

&lt;h2 id=&quot;retry-语句&quot;&gt;retry 语句&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;retry
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果 retry 出现在 begin 表达式的 rescue 子句中，则从 begin 主体的开头重新开始。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;begin
   do_something # 抛出的异常
rescue
   # 处理错误
   retry  # 重新从 begin 开始
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果 retry 出现在迭代内、块内或者 for 表达式的主体内，则重新开始迭代调用。迭代的参数会重新评估。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;for i in 1..5
   retry if some_condition # 重新从 i == 1 开始
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;retry&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;局部变量的值为 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这将产生以下结果，并会进入一个无限循环：
</description>
        <pubDate>Mon, 24 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/ruby-loops/</link>
        <guid isPermaLink="true">https://wsdjeg.net/ruby-loops/</guid>
        
        <category>ruby</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>ruby 流程控制</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#ifelse-语句&quot; id=&quot;markdown-toc-ifelse-语句&quot;&gt;if…else 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#if-修饰符&quot; id=&quot;markdown-toc-if-修饰符&quot;&gt;if 修饰符&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#unless-语句&quot; id=&quot;markdown-toc-unless-语句&quot;&gt;unless 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#unless-修饰符&quot; id=&quot;markdown-toc-unless-修饰符&quot;&gt;unless 修饰符&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#case-语句&quot; id=&quot;markdown-toc-case-语句&quot;&gt;case 语句&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

Ruby 提供了其他现代语言中很常见的条件结构。在这里，我们将解释所有的条件语句和 Ruby 中可用的修饰符。

&lt;h2 id=&quot;ifelse-语句&quot;&gt;if…else 语句&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if conditional [then]
   code...
[elsif conditional [then]
    code...]...
[else
    code...]
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

if 表达式用于条件执行。值 false 和 nil 为假，其他值都为真。请注意，Ruby 使用 elsif，不是使用 else if 和 elif。
如果 conditional 为真，则执行 code。如果 conditional 不为真，则执行 else 子句中指定的 code。
通常我们省略保留字 then 。若想在一行内写出完整的 if 式，则必须以 then 隔开条件式和程式区块。如下所示:

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;x 大于 2&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x!&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;x 是 1&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;无法得知 x 的值&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/62419681-b9dcbe00-b6b8-11e9-907a-aedd3a797f32.png&quot; alt=&quot;图片&quot; /&gt;

&lt;h2 id=&quot;if-修饰符&quot;&gt;if 修饰符&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;code if condition
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果 conditional 为真，则执行 code。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;

&lt;span class=&quot;vg&quot;&gt;$debug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;debug&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$debug&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/62419702-66b73b00-b6b9-11e9-95d0-21584614add6.png&quot; alt=&quot;图片&quot; /&gt;

&lt;h2 id=&quot;unless-语句&quot;&gt;unless 语句&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;unless conditional [then]
   code
[else
   code ]
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

unless 式和 if 式作用相反，即如果 conditional 为假，则执行 code。如果 conditional 为真，则执行 else 子句中指定的 code。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;x 小于 2&quot;&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;x 大于 2&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/62419722-cca3c280-b6b9-11e9-807e-f6c7b88420b8.png&quot; alt=&quot;图片&quot; /&gt;

&lt;h2 id=&quot;unless-修饰符&quot;&gt;unless 修饰符&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;code unless conditional
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果 conditional 为假，则执行 code。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;vg&quot;&gt;$var&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;1 -- 这一行输出&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$var&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;2 -- 这一行不输出&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$var&lt;/span&gt;

&lt;span class=&quot;vg&quot;&gt;$var&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;3 -- 这一行输出&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$var&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/62419738-3d4adf00-b6ba-11e9-855d-c90a4b01cf52.png&quot; alt=&quot;图片&quot; /&gt;

&lt;h2 id=&quot;case-语句&quot;&gt;case 语句&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;case expression
[when expression [, expression ...] [then]
   code ]...
[else
   code ]
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

case 先对一个 expression 进行匹配判断，然后根据匹配结果进行分支选择。

它使用 ===运算符比较 when 指定的 expression，若一致的话就执行 when 部分的内容。

通常我们省略保留字 then 。若想在一行内写出完整的 when 式，则必须以 then 隔开条件式和程式区块。如下所示:

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;when a == 4 then a = 7 end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

因此：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;case expr0
when expr1, expr2
   stmt1
when expr3, expr4
   stmt2
else
   stmt3
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

基本上类似于：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;_tmp = expr0
if expr1 === _tmp || expr2 === _tmp
   stmt1
elsif expr3 === _tmp || expr4 === _tmp
   stmt2
else
   stmt3
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding: UTF-8 -*-&lt;/span&gt;

&lt;span class=&quot;vg&quot;&gt;$age&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$age&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;婴儿&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;小孩&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;child&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;少年&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;其他年龄段的&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/62419785-5902b500-b6bb-11e9-85a4-130587abf2a2.png&quot; alt=&quot;图片&quot; /&gt;

</description>
        <pubDate>Thu, 20 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/ruby-decision-making/</link>
        <guid isPermaLink="true">https://wsdjeg.net/ruby-decision-making/</guid>
        
        <category>ruby</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Ruby 运算符</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#算术运算符&quot; id=&quot;markdown-toc-算术运算符&quot;&gt;算术运算符&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#比较运算符&quot; id=&quot;markdown-toc-比较运算符&quot;&gt;比较运算符&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#赋值运算符&quot; id=&quot;markdown-toc-赋值运算符&quot;&gt;赋值运算符&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#并行赋值&quot; id=&quot;markdown-toc-并行赋值&quot;&gt;并行赋值&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;算术运算符&quot;&gt;算术运算符&lt;/h2&gt;

算数运算符，顾名思义，常见的加减乘除，还有取余等：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;运算符&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
      &lt;th&gt;实例&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;+&lt;/td&gt;
      &lt;td&gt;加法 - 把运算符两边的操作数相加&lt;/td&gt;
      &lt;td&gt;a + b 将得到 30&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;减法 - 把左操作数减去右操作数&lt;/td&gt;
      &lt;td&gt;a - b 将得到 -10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;*&lt;/td&gt;
      &lt;td&gt;乘法 - 把运算符两边的操作数相乘&lt;/td&gt;
      &lt;td&gt;a * b 将得到 200&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/&lt;/td&gt;
      &lt;td&gt;除法 - 把左操作数除以右操作数&lt;/td&gt;
      &lt;td&gt;b / a 将得到 2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;%&lt;/td&gt;
      &lt;td&gt;求模 - 把左操作数除以右操作数，返回余数&lt;/td&gt;
      &lt;td&gt;b % a 将得到 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;**&lt;/td&gt;
      &lt;td&gt;指数 - 执行指数计算&lt;/td&gt;
      &lt;td&gt;a**b 将得到 10 的 20 次方&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;比较运算符&quot;&gt;比较运算符&lt;/h2&gt;

假设变量 a 的值为 10，变量 b 的值为 20，那么：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;运算符&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
      &lt;th&gt;实例&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;==&lt;/td&gt;
      &lt;td&gt;检查两个操作数的值是否相等，如果相等则条件为真。&lt;/td&gt;
      &lt;td&gt;(a == b) 不为真。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;!=&lt;/td&gt;
      &lt;td&gt;检查两个操作数的值是否相等，如果不相等则条件为真。&lt;/td&gt;
      &lt;td&gt;(a != b) 为真。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;gt;&lt;/td&gt;
      &lt;td&gt;检查左操作数的值是否大于右操作数的值，如果是则条件为真。&lt;/td&gt;
      &lt;td&gt;(a &amp;gt; b) 不为真。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;&lt;/td&gt;
      &lt;td&gt;检查左操作数的值是否小于右操作数的值，如果是则条件为真。&lt;/td&gt;
      &lt;td&gt;(a &amp;lt; b) 为真。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;gt;=&lt;/td&gt;
      &lt;td&gt;检查左操作数的值是否大于或等于右操作数的值，如果是则条件为真。&lt;/td&gt;
      &lt;td&gt;(a &amp;gt;= b) 不为真。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;=&lt;/td&gt;
      &lt;td&gt;检查左操作数的值是否小于或等于右操作数的值，如果是则条件为真。&lt;/td&gt;
      &lt;td&gt;(a &amp;lt;= b) 为真。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;=&amp;gt;&lt;/td&gt;
      &lt;td&gt;联合比较运算符。如果第一个操作数等于第二个操作数则返回 0，如果第一个操作数大于第二个操作数则返回 1，如果第一个操作数小于第二个操作数则返回 -1。&lt;/td&gt;
      &lt;td&gt;(a &amp;lt;=&amp;gt; b) 返回 -1。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;===&lt;/td&gt;
      &lt;td&gt;用于测试 case 语句的 when 子句内的相等。&lt;/td&gt;
      &lt;td&gt;(1…10) === 5 返回 true。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.eql?&lt;/td&gt;
      &lt;td&gt;如果接收器和参数具有相同的类型和相等的值，则返回 true。&lt;/td&gt;
      &lt;td&gt;1 == 1.0 返回 true，但是 1.eql?(1.0) 返回 false。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;equal?&lt;/td&gt;
      &lt;td&gt;如果接收器和参数具有相同的对象 id，则返回 true。&lt;/td&gt;
      &lt;td&gt;如果 aObj 是 bObj 的副本，那么 aObj == bObj 返回 true，a.equal?bObj 返回 false，但是 a.equal?aObj 返回 true。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;赋值运算符&quot;&gt;赋值运算符&lt;/h4&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;运算符&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
      &lt;th&gt;实例&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;=&lt;/td&gt;
      &lt;td&gt;简单的赋值运算符，把右操作数的值赋给左操作数&lt;/td&gt;
      &lt;td&gt;c = a + b 将把 a + b 的值赋给 c&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;+=&lt;/td&gt;
      &lt;td&gt;加且赋值运算符，把右操作数加上左操作数的结果赋值给左操作数&lt;/td&gt;
      &lt;td&gt;c += a 相当于 c = c + a&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;-=&lt;/td&gt;
      &lt;td&gt;减且赋值运算符，把左操作数减去右操作数的结果赋值给左操作数&lt;/td&gt;
      &lt;td&gt;c -= a 相当于 c = c - a&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;*=&lt;/td&gt;
      &lt;td&gt;乘且赋值运算符，把右操作数乘以左操作数的结果赋值给左操作数&lt;/td&gt;
      &lt;td&gt;c _= a 相当于 c = c _ a&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/=&lt;/td&gt;
      &lt;td&gt;除且赋值运算符，把左操作数除以右操作数的结果赋值给左操作数&lt;/td&gt;
      &lt;td&gt;c /= a 相当于 c = c / a&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;%=&lt;/td&gt;
      &lt;td&gt;求模且赋值运算符，求两个操作数的模赋值给左操作数&lt;/td&gt;
      &lt;td&gt;c %= a 相当于 c = c % a&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;**=&lt;/td&gt;
      &lt;td&gt;指数且赋值运算符，执行指数计算，并赋值给左操作数&lt;/td&gt;
      &lt;td&gt;c **= a 相当于 c = c ** a&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;并行赋值&quot;&gt;并行赋值&lt;/h2&gt;

Ruby 也支持变量的并行赋值。这使得多个变量可以通过一行的 Ruby 代码进行初始化。例如：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

使用并行赋值可以更快地声明：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

并行赋值在交换两个变量的值时也很有用：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Wed, 12 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/ruby-miscellaneous-operator/</link>
        <guid isPermaLink="true">https://wsdjeg.net/ruby-miscellaneous-operator/</guid>
        
        <category>ruby</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>如何在 Vim 内进行高效的排序</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#排序命令&quot; id=&quot;markdown-toc-排序命令&quot;&gt;排序命令&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#排序函数&quot; id=&quot;markdown-toc-排序函数&quot;&gt;排序函数&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

Vim 分别提供了排序函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sort()&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uniq()&lt;/code&gt; 和排序命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:sort&lt;/code&gt;。机遇这两种方式，可以在 Vim 内对文本进行高效的排序。
下面分两部分详细说明下这两种方式的使用方法。

&lt;h4 id=&quot;排序命令&quot;&gt;排序命令&lt;/h4&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:sort&lt;/code&gt; 命令的用法格式如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:[range]sor[t][!] [b][f][i][n][o][r][u][x] [/{pattern}/]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt; 值得是一个范围，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:sort&lt;/code&gt; 命令会基于这个范围进行排序，当未制定范围时，会对整个文档进行排序。关于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt; 的常用方法有下面几种：

我们看到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sor[t]&lt;/code&gt; 最后一个字母 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t&lt;/code&gt; 被方括号包围，表示该字母可以省略，即更简单地执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:sor&lt;/code&gt; 命令。
在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:sort&lt;/code&gt;命令紧接其后的感叹号 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt; 表示是否进行反向排序，不带感叹号则是正向排序，带上则反之。
在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:sort&lt;/code&gt; 命令紧接其后的第一个参数为可选参数，包括 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;o&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;。首先，需要了解选项 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;o&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; 之间是互斥的，也就是说不可以同时使用这些选项，换句话说。前面的这个五个选项可以和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u&lt;/code&gt; 这三项组合使用。下面分别说下这些参数的意义：

&lt;ul&gt;
  &lt;li&gt;带 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; 则排序基于每行的第一个十进制数 (在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{pattern}&lt;/code&gt; 匹配之后或之内)。数值包含前导的 ‘-‘。&lt;/li&gt;
  &lt;li&gt;带 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; 则排序基于每行的第一个浮点数。浮点值相当于在文本( &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{pattern}&lt;/code&gt; 匹配的之后或之内) 上调用 str2float() 函数的结果。仅当 Vim 编译时加入浮点数支持时该标志位才有效。&lt;/li&gt;
  &lt;li&gt;带 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; 则排序基于每行的第一个十六进制数 (在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{pattern}&lt;/code&gt; 匹配之后或之内)。忽略该数值前的 “0x” 或 “0X”。但包含前导的 ‘-‘。&lt;/li&gt;
  &lt;li&gt;带 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;o&lt;/code&gt; 则排序基于每行的第一个八进制数 (在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{pattern}&lt;/code&gt; 匹配之后或之内)。&lt;/li&gt;
  &lt;li&gt;带 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; 则排序基于每行的第一个二进制数 (在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{pattern}&lt;/code&gt; 匹配之后或之内)。&lt;/li&gt;
  &lt;li&gt;带 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u&lt;/code&gt; (u 代表 unique 唯一) 则只保留完全相同的行的第一行 (如果同时带 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;，忽略大小写的区别)。没有这个标志位，完全相同的行的序列会按照它们原来的顺序被保留下来。
注意： 行首和行尾的的空白差异会影响唯一性的判定。&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;排序函数&quot;&gt;排序函数&lt;/h4&gt;

Vim 提供两个排序相关的函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sort()&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uniq()&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sort()&lt;/code&gt; 这个函数的用法如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sort({list} [, {func} [, {dict}]])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

给定一个 List 经过排序后，返回一个结果，同样也是 List。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sort()&lt;/code&gt; 这一函数第二个参数可以接受如下几种情况：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;: 表示忽略大小写。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;：按照数值排序，即使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strtod()&lt;/code&gt; 解析 List 内的元素，字符串、列表、字典和函数引用均视作 0。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt;：按照浮点数值来排序，要求给定的 List 每一个选项都是浮点数。&lt;/li&gt;
  &lt;li&gt;一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Funcref&lt;/code&gt; 变量。这个变量表示的是一个函数，则调用该函数来比较项目，该函数会使用两个项目作为参数，根据返回值确定两个项目关系。 0 表示相等，1 或者更高，表示第一个排在第二个之后，-1 或更小代表第一个排在第二个之前。&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 07 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/how-to-sort-efficiently-in-vim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/how-to-sort-efficiently-in-vim/</guid>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>(Neo)Vim 插件开发指南</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#简介&quot; id=&quot;markdown-toc-简介&quot;&gt;简介&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#基本语法&quot; id=&quot;markdown-toc-基本语法&quot;&gt;基本语法&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#注释&quot; id=&quot;markdown-toc-注释&quot;&gt;注释&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#变量&quot; id=&quot;markdown-toc-变量&quot;&gt;变量&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#作用域&quot; id=&quot;markdown-toc-作用域&quot;&gt;作用域&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#函数定义&quot; id=&quot;markdown-toc-函数定义&quot;&gt;函数定义&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#插件的目录结构&quot; id=&quot;markdown-toc-插件的目录结构&quot;&gt;插件的目录结构&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#vim-自定义命令&quot; id=&quot;markdown-toc-vim-自定义命令&quot;&gt;Vim 自定义命令&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;简介&quot;&gt;简介&lt;/h2&gt;

(Neo)Vim 插件开发中文指南，主要包括 Vim 脚本语法、插件开发技巧等。

&lt;h2 id=&quot;基本语法&quot;&gt;基本语法&lt;/h2&gt;

&lt;h3 id=&quot;注释&quot;&gt;注释&lt;/h3&gt;

在写脚本时，经常需要在源码里面添加一些注释信息，辅助阅读源码，Vim 脚本注释比较简单，是以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;&lt;/code&gt; 开头的，只存在行注释，不存在块注释。因此，对于多行注释，需要再每行开头添加 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;&lt;/code&gt;。

示例：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot; 这是一行注释，&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:helloworld&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;  &quot; 这是在行尾注释
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;变量&quot;&gt;变量&lt;/h3&gt;

在 Vim 脚本里，可以使用关键字 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let&lt;/code&gt; 来申明变量，最基本的方式为：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot; 定义一个类型是字符串的变量 g:helloworld&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:helloworl&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;sss&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

前面的例子中，是定义一个字符串，Vim 脚本中支持以下几种数据类型：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;类型&lt;/th&gt;
      &lt;th&gt;ID&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Number&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;整数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;String&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;字符串&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Funcref&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;函数指针&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;List&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;列表&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Dictionary&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;字典&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Float&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;浮点数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Boolean&lt;/td&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;None&lt;/td&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Job&lt;/td&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Channel&lt;/td&gt;
      &lt;td&gt;9&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;作用域&quot;&gt;作用域&lt;/h3&gt;

Vim 变量存在三种作用域，全局变量、局部变量、和脚本变量。通常，我们以不同的前缀来区别作用域，比如使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g:&lt;/code&gt; 表示全局变量，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s:&lt;/code&gt; 表示脚本变量。
在一些特殊情况下，前缀是可以省略的，Vim 会为该变量选择默认的作用域。不同的情况下，默认的作用域是不一样的，在函数内部，默认作用域是局部变量，
而在函数外部，默认作用域是全局变量：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:helloworld&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;  &quot; 这是一个全局变量， &lt;span class=&quot;k&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; 前缀未省略
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; helloworld &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;    &quot; 这也是一个全局变量，在函数外部，默认的作用域是全局的

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; HelloWorld&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:helloworld&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;    &quot; 这是函数内部全局变量
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; helloworld &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;      &quot; 这是一个函数内部的局部变量，在函数内部，默认的作用域为局部变量
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;前缀&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g:&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;全局变量&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;l:&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;局部变量，只可在函数内部使用&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s:&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;脚本变量，只可以在当前脚本函数内使用&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v:&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Vim 特殊变量&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b:&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;作用域限定在某一个缓冲区内&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w:&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;作用域限定在窗口内部&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t:&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;作用域限定在标签内部&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

此外，在开发 Vim 插件之前，你还需要了解 vimrc 和 Vim 插件的区别。

&lt;h3 id=&quot;函数定义&quot;&gt;函数定义&lt;/h3&gt;

可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function&lt;/code&gt; 关键字定义函数，可缩写成 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;func&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fn&lt;/code&gt;, 格式：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:fu[nction][!] {name}([arguments]) [range] [abort] [dict] [closure]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当使用了参数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;closure&lt;/code&gt; 时，函数可以访问外部的变量或者参数，比如：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; Foo&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; Bar&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; closure
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;funcref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Bar&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; F &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; Foo&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

echo F&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; 1&lt;/span&gt;
echo F&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; 2&lt;/span&gt;
echo F&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;插件的目录结构&quot;&gt;插件的目录结构&lt;/h2&gt;

在开发插件之前，需要了解下一个插件项目的目录结构是怎样的，以及每一个目录里文件的意义是什么。

插件标准的目录结构为：

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autoload/               自动载入脚本
colors/                 颜色主题
plugin/                 在 Vim 启动时将被载入的脚本
ftdetect/               文件类型识别脚本
syntax/                 语法高亮文件
ftplugin/               文件类型相关插件
compiler/	              编译器
indent/                 语法对齐
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

下面，我们来逐一说明下每一个目录的用途：

&lt;strong&gt;autoload/&lt;/strong&gt;

顾名思义，该文件夹下的脚本会在特点条件下自动被载入。这里的特定条件指的是当某一个 autoload 类型的函数被调用，并且 Vim 当前环境下并未定义该函数时。
比如调用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;call helloworld#init()&lt;/code&gt; 时，Vim 会先检测当前环境下是否定义了该函数，若没有，则在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoload/&lt;/code&gt; 目录下找 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;helloworld.vim&lt;/code&gt; 这一文件，
并将其载入，载入完成后执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;call helloworld#init()&lt;/code&gt;.

&lt;strong&gt;plugin/&lt;/strong&gt;

该目录里的文件将在 Vim 启动时被运行，作为一个优秀的 Vim 插件，应当尽量该目录下的脚本内容。通常，可以将插件的快捷键、命令的定义保留在这个文件里。

&lt;strong&gt;ftdetect/&lt;/strong&gt;

ftdetect 目录里通常存放的是文件类型检测脚本，该目录下的文件也是在 Vim 启动时被载入的。在这一目录里的文件内容，通常比较简单，比如：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;BufNewFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;BufRead&lt;/span&gt; *&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;helloworld &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;filetype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;helloworld
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上脚本使得 Vim 在打开以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.helloworld&lt;/code&gt; 为后缀的文件时，将文件类型设置为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;helloworld&lt;/code&gt;。通常，这个脚本的文件名是和所需要设置的文件类型一样的，上面的例子中文件的名称就是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;helloworld.vim&lt;/code&gt;。

&lt;strong&gt;syntax/&lt;/strong&gt;

这一目录下的文件，主要是定义语法高亮的。通常文件名前缀和对应的语言类型相同，比如 Java 的语法文件文件名为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.vim&lt;/code&gt;。 关于如何写语法文件，将在后面详细介绍。

&lt;strong&gt;colors/&lt;/strong&gt;

colors 目录下主要存储一些颜色主题脚本，当执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:colorscheme + 主题名&lt;/code&gt; 命令时，对应的颜色主题脚本将被载入。比如执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:colorscheme helloworld&lt;/code&gt; 时，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;colors/helloworld.vim&lt;/code&gt; 这一脚本将被载入。

&lt;strong&gt;compiler/&lt;/strong&gt;

这一名录里是一些预设的编译器参数，主要给 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:make&lt;/code&gt; 命令使用的。在最新版的 Vim 中可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:compiler! 编译器名&lt;/code&gt; 来为当前缓冲区设定编译器。比如当执行
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:compiler! helloworld&lt;/code&gt; 时，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compiler/helloworld.vim&lt;/code&gt; 这一脚本将被载入。

&lt;strong&gt;indent/&lt;/strong&gt;

在 indent 目录里，主要是一些语法对齐相关的脚本。

&lt;h2 id=&quot;vim-自定义命令&quot;&gt;Vim 自定义命令&lt;/h2&gt;

Vim 的自定义命令可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;command&lt;/code&gt; 命令来定义，比如：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;command&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;nargs&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;* &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;custom&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;helloworld#&lt;span class=&quot;nb&quot;&gt;complete&lt;/span&gt; HelloWorld &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; helloworld#test&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

紧接 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;command&lt;/code&gt; 命令其后的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt; 表示强制定义该命令，即使前面已经定义过了同样名称的命令，也将其覆盖掉。 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-nargs=*&lt;/code&gt; 表示，该命令可接受任意个数的参数，
包括 0 个。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-nargs&lt;/code&gt; 的取值有以下几种情况：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;参数&lt;/th&gt;
      &lt;th&gt;定义&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-nargs=0&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;不接受任何参数（默认）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-nagrs=1&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;只接受一个参数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-nargs=*&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;可接收任意个数参数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-nargs=?&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;可接受 1 个或者 0 个参数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-nargs=+&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;至少提供一个参数&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=custom,helloworld#complete&lt;/code&gt; 表示，改命令的补全方式采用的是自定义函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;helloworld#complete&lt;/code&gt;。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete&lt;/code&gt; 可以接受的参数包括如下内容：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;参数&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=augroup&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;autocmd 组名&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=buffer&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;buffer 名称&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=behave&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:behave&lt;/code&gt; 命令子选项&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=color&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;颜色主题&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=command&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Ex 命令及参数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=compiler&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;编译器&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=cscope&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:cscope&lt;/code&gt; 命令子选项&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=dir&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;文件夹名称&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=environment&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;环境变量名称&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=event&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;自动命令的事件名称&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=expression&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Vim 表达式&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=file&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;文件及文件夹名称&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=file_in_path&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;path&lt;/code&gt; 选项里的文件及文件夹名称&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=filetype&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;文件类型&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=function&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;函数名称&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=help&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;帮助命令子选项&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=highlight&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;高亮组名称&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=history&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:history&lt;/code&gt; 子选项&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=locale&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;locale 名称（相当于命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;locale -a&lt;/code&gt; 的输出）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=mapping&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;快捷键名称&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=menu&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;目录&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=messages&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:messages&lt;/code&gt; 命令子选项&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=option&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Vim 选项名称&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=packadd&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;可选的插件名称补全&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=shellcmd&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;shell 命令补全&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=sign&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:sign&lt;/code&gt; 命令补全&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=syntax&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;语法文件名称补全&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=syntime&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:syntime&lt;/code&gt; 命令补全&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=tag&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;tags&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=tag_listfiles&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;tags, file names are shown when CTRL-D is hit&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=user&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;user names&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=var&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;user variables&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=custom,{func}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;custom completion, defined via {func}&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=customlist,{func}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;custom completion, defined via {func}&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

这里主要解释一些自定义的补全函数，从上面的表格可以看出，有两种定义自定义命令补全函数的方式。
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=custom,{func}&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=customlist,{func}&lt;/code&gt;。这两种区别在与函数的返回值，
前者要求是一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt; 而后者要求补全函数的返回值是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list&lt;/code&gt;.
自定义命令补全函数接受三个参数。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;func&lt;span class=&quot;p&quot;&gt;}(&lt;/span&gt;ArgLead&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; CmdLine&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; CursorPos&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

我们以实际的例子来解释这三个参数的含义，比如在命令行是如下内容时，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt; 表示光标位置，我按下了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Tab&amp;gt;&lt;/code&gt; 键调用了补全函数，那么传递给补全函数的三个参数分别是：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;HelloWorld hello&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;参数名&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArgLead&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前需要补全的部分，通常是光标前的字符串，上面的例子中是指 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CmdLine&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;指的是整个命令行内的内容，此时是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HelloWorld hello&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CursorPos&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;指的当前光标所在的位置，此时是 16, 即为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;len(&apos;HelloWorld hello&apos;)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

下面，我们来看下定义的函数具体内容：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; helloworld#&lt;span class=&quot;nb&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;ArgLead&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; CmdLine&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; CursorPos&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; abort
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;hellolily&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;hellojeky&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;hellofoo&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;world&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;            \&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在上面的函数里，返回的实际上是一个有四行的字符串，Vim 会自动根据 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArgLead&lt;/code&gt; 来筛选出可以用来补全的选项，并展示在状态栏上。
此时，四行里最后一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;world&lt;/code&gt; 因为开头不匹配 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArgLead&lt;/code&gt; 所以不会被展示在状态栏上，因此补全效果只有三个可选项。

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/44915590-f2b43a80-ad65-11e8-92aa-0f4eac3a0a26.gif&quot; alt=&quot;command-complete&quot; /&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-complete=customlist,{func}&lt;/code&gt; 这一参数所对应的补全函数，也是接受相同的三个参数，但该函数返回的是一个 list。

下面，我们来测试这个函数：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; helloworld#&lt;span class=&quot;nb&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;ArgLead&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; CmdLine&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; CursorPos&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; abort
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;hellolily&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;hellojeky&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;hellofoo&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;world&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/44916266-e03b0080-ad67-11e8-9cb8-535a970768e4.gif&quot; alt=&quot;command-complete&quot; /&gt;

区别很明显，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;customlist&lt;/code&gt; 补全时不会自动根据 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArgLead&lt;/code&gt; 进行筛选，并且直接补全整个返回的 list，即使列表中有一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;world&lt;/code&gt; 完全与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArgLead(hello)&lt;/code&gt; 不同，
也会将其直接覆盖。因此，当使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;customlist&lt;/code&gt; 时，需要在函数内根据 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArgLead&lt;/code&gt; 进行筛选，将函数该为如下，就可以得到相同效果了：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; helloworld#&lt;span class=&quot;nb&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;ArgLead&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; CmdLine&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; CursorPos&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; abort
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;hellolily&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;hellojeky&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;hellofoo&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;world&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;v:val =~ &quot;^&quot; . a:ArgLead&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-bang&lt;/code&gt; 参数：&lt;/li&gt;
&lt;/ul&gt;

在定义 Vim 自定义命令时，可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-bang&lt;/code&gt; 参数来申明这个命令接受感叹号。比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:q&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:q!&lt;/code&gt;。
下面是一个实例：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;bang&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:bang&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;带有叹号&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;不带有叹号&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endf&lt;/span&gt;
command&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;bang Hello &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&amp;lt;&lt;/span&gt;bang&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在上面的实例里，函数的参数写法为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;bang&amp;gt;0&lt;/code&gt;, 当执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Hello!&lt;/code&gt; 时，传递给 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s:hello&lt;/code&gt; 这一函数的参数是
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!0&lt;/code&gt; 即为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;，因此，此时看到打印了”带有叹号“。

其实除了写成 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;bang&amp;gt;0&lt;/code&gt;, 还可以写 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;bang&amp;gt;1&lt;/code&gt;, 甚至是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;bang&amp;gt;&lt;/code&gt; + 一个全局变量。比如：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:hello&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;bang&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a:bang&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;带有叹号&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;echom&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;不带有叹号&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endf&lt;/span&gt;
command&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;bang Hello &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&amp;lt;&lt;/span&gt;bang&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;g:hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 31 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/vim-plugin-dev-guide/</link>
        <guid isPermaLink="true">https://wsdjeg.net/vim-plugin-dev-guide/</guid>
        
        <category>neovim</category>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>如何配置 SpaceVim</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#设置-spacevim-选项&quot; id=&quot;markdown-toc-设置-spacevim-选项&quot;&gt;设置 SpaceVim 选项&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#启用禁用--模块&quot; id=&quot;markdown-toc-启用禁用--模块&quot;&gt;启用/禁用   模块&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#添加自定义插件&quot; id=&quot;markdown-toc-添加自定义插件&quot;&gt;添加自定义插件&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#自定义快捷键及插件配置&quot; id=&quot;markdown-toc-自定义快捷键及插件配置&quot;&gt;自定义快捷键及插件配置&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

本文将系统地介绍如何配置 SpaceVim，配置  SpaceVim  主要包括以下几个内容：

&lt;ul&gt;
  &lt;li&gt;设置  SpaceVim  选项&lt;/li&gt;
  &lt;li&gt;启动/禁用模块&lt;/li&gt;
  &lt;li&gt;添加自定义插件&lt;/li&gt;
  &lt;li&gt;添加自定义按键映射以及插件配置&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;设置-spacevim-选项&quot;&gt;设置 SpaceVim 选项&lt;/h4&gt;

原先，在老版本的 SpaceVim 中，默认的配置文件是 init.vim。在  init.vim  文件内，我们可以通过  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let g:spacevim_*&lt;/code&gt; 这样的语句来设置 SpaceVim 选项。而在新版的  SpaceVim  中，我们采用了  toml  作为默认配置文件，如果不熟悉  toml  语法的，可以先阅读一下  toml  的基本语法，当然不读也没关系，
toml  已经是最简单的配置文件格式了。
所有的  SpaceVim  选项配置在一个字典里，key  为原先的选项名去除  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g:spacevim_&lt;/code&gt; 前缀：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;g:spacevim_enable_guicolors -&amp;gt; enable_guicolors
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这一选项的值可为  true  或者  false，于是，写入配置即为：

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enable_guicolors&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

一些其他选项，有的值是数字，有的是字符串，字符串的格式和  vim script  类似，可以用单引号，也可以用双引号，比如：

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enable_guicolors&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;snippet_engine&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;neosnippet&quot;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;statusline_separator&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;arrow&apos;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sidebar_width&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;启用禁用--模块&quot;&gt;启用/禁用   模块&lt;/h4&gt;

SpaceVim  内置了很多模块，每一个模块由一些插件和相关配置组成，用于提供一些特定的功能，比如提供模糊搜索的模块，
提供版本控制的模块，以及提供语言开发支持的语言模块。
启用或者禁用模块，需要遵循一定的语法结构，并且配到  layers  列表内，比如我现在需要启用  shell  模块，设置模块选项
default_position  和  default_height,  这两个选项分别控制这  shell  窗口打开位置和高度：

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]]&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;shell&quot;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default_position&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;top&quot;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default_height&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果要禁用一个模块，需要增添一个选项  enable,  并赋值  false，默认这个是  true。比如，我需要禁用  shell  模块，
可以这么写,  禁用模块时，除了  enable  这选项，其他选项可写可不写，因为已经不会生效。当然如果为了快速启用/禁用模块，
可以保持其他选项不变。

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]]&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;shell&quot;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enable&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;添加自定义插件&quot;&gt;添加自定义插件&lt;/h4&gt;

自定义插件配置语法和模块有点类似，将需要配置的插件，配置进  custom_plugins  列表。比如，我需要添加  2  个插件，
可以参考以下语法：

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;custom_plugins&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]]&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;lilydjwg/colorizer&quot;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;merged&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;custom_plugins&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]]&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tpope/vim-scriptease&quot;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;merged&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on_cmd&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Scriptnames&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

大家可以看到，在添加自定义插件时，我们支持很多选项，这归功于 dein, dein  支持多种选项。

&lt;h4 id=&quot;自定义快捷键及插件配置&quot;&gt;自定义快捷键及插件配置&lt;/h4&gt;

最后，我们来说下，如果添加自定义配置，和自定义快捷键。在使用  toml  配置  SpaceVim  时，我们提供了两个选项，位于  [options]  下：
bootstrap_before  和  bootstrap_after,  这两个选项接受一个字符串最为值，该字符串值得是一个  vim  方法名。顾名思义，你可以通过这
两个选项定义两个  vim  方法，分别在载入配置时，和  vim  启动后被调用，在方法内，你可以加入一些  vim  脚本，比如快捷键，
比如插件的选项。
比如，在配置文件内加入如下内容：

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enable_guicolors&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;snippet_engine&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;neosnippet&quot;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;statusline_separator&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;arrow&apos;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sidebar_width&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bootstrap_before&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;myspacevim#before&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bootstrap_after&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;myspacevim#after&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

新建  ~/.SpaceVim.d/autoload/myspacevim.vim,  加入内容：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; myspacevim#before&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; abort
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:neomake_enabled_c_makers&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;clang&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    nnoremap jk &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;esc&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endf&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; myspacevim#after&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; abort
&lt;span class=&quot;k&quot;&gt;endf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在上述这个方法内部，目前只定义了一个变量和快捷键，用户可以添加一些其他的 vim 脚本，比如定制一些 autocmd

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;augroup MySpaceVim
  &lt;span class=&quot;k&quot;&gt;au&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;
  autocmd &lt;span class=&quot;nb&quot;&gt;FileType&lt;/span&gt; markdown &lt;span class=&quot;k&quot;&gt;setlocal&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nowrap&lt;/span&gt;
augroup END
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

也是应大多数人要求，更新的这篇文字，仓促之下，有很多内容可能还不完整，如果有什么疑问，欢迎留言。
</description>
        <pubDate>Tue, 28 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/how-to-config-spacevim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/how-to-config-spacevim/</guid>
        
        <category>spacevim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Ruby 数据类型</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#数值类型number&quot; id=&quot;markdown-toc-数值类型number&quot;&gt;数值类型(Number)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

Ruby支持的数据类型包括基本的Number、String、Ranges、Symbols，以及true、false和nil这几个特殊值，同时还有两种重要的数据结构——Array和Hash。

&lt;h2 id=&quot;数值类型number&quot;&gt;数值类型(Number)&lt;/h2&gt;

1、整型(Integer)

整型分两种，如果在31位以内（四字节），那为Fixnum实例。如果超过，即为Bignum实例。

整数范围从 -230 到 230-1 或 -262 到 262-1。在这个范围内的整数是类 Fixnum 的对象，在这个范围外的整数存储在类 Bignum 的对象中。

您可以在整数前使用一个可选的前导符号，一个可选的基础指标（0 对应 octal，0x 对应 hex，0b 对应 binary），后跟一串数字。下划线字符在数字字符串中被忽略。

您可以获取一个 ASCII 字符或一个用问号标记的转义序列的整数值。

实例

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;123                  # Fixnum 十进制
1_234                # Fixnum 带有下划线的十进制
-500                 # 负的 Fixnum
0377                 # 八进制
0xff                 # 十六进制
0b1011               # 二进制
?a                   # &apos;a&apos; 的字符编码
?\n                  # 换行符（0x0a）的编码
12345678901234567890 # Bignum
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#整型 Integer 以下是一些整型字面量 
#字面量（literal）：代码中能见到的值，数值，bool值，字符串等都叫字面量 
#如以下的0,1_000_000,0xa等 
a1=0 

#带千分符的整型 
a2=1_000_000 

#其它进制的表示 
a3=0xa 
puts a1,a2 
puts a3 

#puts print 都是向控制台打印字符，其中puts带回车换行符 
=begin 
这是注释，称作：嵌入式文档注释 
类似C#中的/**/ 
=end 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

浮点型

Ruby 支持浮点数。它们是带有小数的数字。浮点数是类 Float 的对象，且可以是下列中任意一个。

实例

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;123.4                # 浮点值
1.0e6                # 科学记数法
4E20                 # 不是必需的
4e+20                # 指数前的符号
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#浮点型 
f1=0.0 
f2=2.1 
f3=1000000.1 
puts f3  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

算术操作

加减乘除操作符：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+-*/&lt;/code&gt;；指数操作符为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;**&lt;/code&gt;

指数不必是整数，例如

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#指数算术 
puts 2**(1/4)#1与4的商为0，然后2的0次方为1 
puts 16**(1/4.0)#1与4.0的商为0.25（四分之一），然后开四次方根 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

字符串类型

Ruby 字符串简单地说是一个 8 位字节序列，它们是类 String 的对象。

双引号标记的字符串允许替换和使用反斜线符号，单引号标记的字符串不允许替换，且只允许使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\\&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&apos;&lt;/code&gt; 两个反斜线符号。

实例

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/ruby -w

puts &apos;escape using &quot;\\&quot;&apos;;
puts &apos;That\&apos;s right&apos;;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

实例

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/ruby -w

puts &apos;escape using &quot;\\&quot;&apos;;
puts &apos;That\&apos;s right&apos;;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这将产生以下结果：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;escape using &quot;\&quot;
That&apos;s right
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

您可以使用序列 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#{ expr }&lt;/code&gt; 替换任意 Ruby 表达式的值为一个字符串。在这里，expr 可以是任意的 Ruby 表达式。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/ruby -w

puts &quot;Multiplication Value : #{24*60*60}&quot;;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这将产生以下结果：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Multiplication Value : 86400
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/ruby -w

name=&quot;Ruby&quot; 
puts name 
puts &quot;#{name+&quot;,ok&quot;}&quot; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Ruby
Ruby,ok
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

反斜线符号

下表列出了 Ruby 支持的反斜线符号：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;符号&lt;/th&gt;
      &lt;th&gt;表示的字符&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;\n&lt;/td&gt;
      &lt;td&gt;换行符 (0x0a)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\r&lt;/td&gt;
      &lt;td&gt;回车符 (0x0d)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\f&lt;/td&gt;
      &lt;td&gt;换页符 (0x0c)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;退格键&lt;/td&gt;
      &lt;td&gt;(0x08)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\a&lt;/td&gt;
      &lt;td&gt;报警符 Bell (0x07)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\e&lt;/td&gt;
      &lt;td&gt;转义符 (0x1b)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\s&lt;/td&gt;
      &lt;td&gt;空格符 (0x20)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\nnn&lt;/td&gt;
      &lt;td&gt;八进制表示法 (n 是 0-7)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\xnn&lt;/td&gt;
      &lt;td&gt;十六进制表示法 (n 是 0-9、a-f 或 A-F)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\cx, \C-x&lt;/td&gt;
      &lt;td&gt;Control-x&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\M-x&lt;/td&gt;
      &lt;td&gt;Meta-x (c | 0x80)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\M-\C-x&lt;/td&gt;
      &lt;td&gt;Meta-Control-x&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\x&lt;/td&gt;
      &lt;td&gt;字符 x&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

如需了解更多有关 Ruby 字符串的细节，请查看 Ruby 字符串（String）。

数组

数组字面量通过[]中以逗号分隔定义，且支持range定义。

（1）数组通过[]索引访问
（2）通过赋值操作插入、删除、替换元素
（3）通过+，－号进行合并和删除元素，且集合做为新集合出现
（4）通过«号向原数据追加元素
（5）通过*号重复数组元素
（6）通过｜和&amp;amp;符号做并集和交集操作（注意顺序）

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;fred&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;This is a string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;last element&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

运行实例 »

这将产生以下结果：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fred
10
3.14
This is a string
last element
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如需了解更多有关 Ruby 数组的细节，请查看 Ruby 数组（Array）。

哈希类型

Ruby 哈希是在大括号内放置一系列键/值对，键和值之间使用逗号和序列 =&amp;gt; 分隔。尾部的逗号会被忽略。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;hsh&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;red&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xf00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;green&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0f0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;blue&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;hsh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; is &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

运行实例 »

这将产生以下结果：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;green is 240
red is 3840
blue is 15
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如需了解更多有关 Ruby 哈希的细节，请查看 Ruby 哈希（Hash）。

范围类型

一个范围表示一个区间。
范围是通过设置一个开始值和一个结束值来表示。范围可使用 s..e 和 s…e 来构造，或者通过 Range.new 来构造。

使用 .. 构造的范围从开始值运行到结束值（包含结束值）。使用 … 构造的范围从开始值运行到结束值（不包含结束值）。当作为一个迭代器使用时，范围会返回序列中的每个值。

范围 (1..5) 意味着它包含值 1, 2, 3, 4, 5，范围 (1…5) 意味着它包含值 1, 2, 3, 4 。

实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这将产生以下结果：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;10 11 12 13 14 15
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Wed, 15 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/ruby-data-types/</link>
        <guid isPermaLink="true">https://wsdjeg.net/ruby-data-types/</guid>
        
        <category>ruby</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Ruby 基本语法</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#程序中的空白&quot; id=&quot;markdown-toc-程序中的空白&quot;&gt;程序中的空白&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#程序中的行尾&quot; id=&quot;markdown-toc-程序中的行尾&quot;&gt;程序中的行尾&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#标识符&quot; id=&quot;markdown-toc-标识符&quot;&gt;标识符&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#保留字&quot; id=&quot;markdown-toc-保留字&quot;&gt;保留字&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#here-document&quot; id=&quot;markdown-toc-here-document&quot;&gt;Here Document&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#begin-语句&quot; id=&quot;markdown-toc-begin-语句&quot;&gt;BEGIN 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#end-语句&quot; id=&quot;markdown-toc-end-语句&quot;&gt;END 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#注释&quot; id=&quot;markdown-toc-注释&quot;&gt;注释&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

让我们编写一个简单的 Ruby 程序。所有的 Ruby 文件扩展名都是 .rb。所以，把下面的源代码放在 test.rb 文件中。
实例

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby -w&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello, Ruby!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在这里，假设您的 /usr/bin 目录下已经有可用的 Ruby 解释器。现在，尝试运行这个程序，如下所示：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ruby test.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这将会产生下面的结果：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Hello, Ruby!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

您已经看到了一个简单的 Ruby 程序，现在让我们看看一些 Ruby 语法相关的基本概念：

&lt;h2 id=&quot;程序中的空白&quot;&gt;程序中的空白&lt;/h2&gt;

在 Ruby 代码中的空白字符，如空格和制表符一般会被忽略，除非当它们出现在字符串中时才不会被忽略。然而，有时候它们用于解释模棱两可的语句。当启用 -w 选项时，这种解释会产生警告。

实例：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;a + b 被解释为 a+b （这是一个局部变量）
a  +b 被解释为 a(+b) （这是一个方法调用）
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;程序中的行尾&quot;&gt;程序中的行尾&lt;/h2&gt;

Ruby 把分号和换行符解释为语句的结尾。但是，如果 Ruby 在行尾遇到运算符，比如 +、- 或反斜杠，它们表示一个语句的延续。

&lt;h2 id=&quot;标识符&quot;&gt;标识符&lt;/h2&gt;

标识符是变量、常量和方法的名称。Ruby 标识符是大小写敏感的。这意味着 Ram 和 RAM 在 Ruby 中是两个不同的标识符。

Ruby 标识符的名称可以包含字母、数字和下划线字符（ _ ）。

&lt;h2 id=&quot;保留字&quot;&gt;保留字&lt;/h2&gt;

下表列出了 Ruby 中的保留字。这些保留字不能作为常量或变量的名称。但是，它们可以作为方法名。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;BEGIN	do	next	then
END	else	nil	true
alias	elsif	not	undef
and	end	or	unless
begin	ensure	redo	until
break	false	rescue	when
case	for	retry	while
class	if	return	while
def	in	self	__FILE__
defined?	module	super	__LINE__
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;here-document&quot;&gt;Here Document&lt;/h2&gt;

“Here Document” 是指建立多行字符串。在 « 之后，您可以指定一个字符串或标识符来终止字符串，且当前行之后直到终止符为止的所有行是字符串的值。

如果终止符用引号括起，引号的类型决定了面向行的字符串类型。请注意« 和终止符之间必须没有空格。

下面是不同的实例：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby -w&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- coding : utf-8 -*-&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
    这是第一种方式创建here document 。
    多行字符串。
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;&quot;EOF&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;c1&quot;&gt;# 与上面相同&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
    这是第二种方式创建here document 。
    多行字符串。
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;`EOC`&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;# 执行命令&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
	echo hi there
	echo lo there
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOC&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;&quot;bar&quot;&lt;/span&gt;	      &lt;span class=&quot;c1&quot;&gt;# 您可以把它们进行堆叠&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
	I said foo.
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
	I said bar.
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;bar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这将产生以下结果：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    This is the first way of creating
    her document ie. multiple line string.
    This is the second way of creating
    her document ie. multiple line string.
hi there
lo there
        I said foo.
        I said bar.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;begin-语句&quot;&gt;BEGIN 语句&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;BEGIN {
   code
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

声明 code 会在程序运行之前被调用。

实例

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/ruby

puts &quot;This is main Ruby Program&quot;

BEGIN {
   puts &quot;Initializing Ruby Program&quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这将产生以下结果：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Initializing Ruby Program
This is main Ruby Program
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;end-语句&quot;&gt;END 语句&lt;/h2&gt;

语法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;END {
   code
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

声明 code 会在程序的结尾被调用。

实例

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/ruby

puts &quot;This is main Ruby Program&quot;

END {
   puts &quot;Terminating Ruby Program&quot;
}
BEGIN {
   puts &quot;Initializing Ruby Program&quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这将产生以下结果：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Initializing Ruby Program
This is main Ruby Program
Terminating Ruby Program
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;注释&quot;&gt;注释&lt;/h2&gt;

注释会对 Ruby 解释器隐藏一行，或者一行的一部分，或者若干行。您可以在行首使用字符（ # ）：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# 我是注释，请忽略我。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

或者，注释可以跟着语句或表达式的同一行的后面：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;name = &quot;Madisetti&quot; # 这也是注释
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

您可以注释多行，如下所示：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# 这是注释。
# 这也是注释。
# 这也是注释。
# 这还是注释。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

下面是另一种形式。这种块注释会对解释器隐藏 =begin/=end 之间的行：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;=begin
这是注释。
这也是注释。
这也是注释。
这还是注释。
=end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 12 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/ruby-basic-syntax/</link>
        <guid isPermaLink="true">https://wsdjeg.net/ruby-basic-syntax/</guid>
        
        <category>ruby</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>初识 Ruby 编程语言</title>
        <description>一直想再多接触一些脚本语言，之前写了一段时间 python 和 lua，感觉都非常不错。之所以要再学习 Ruby，
主要是看到 Ruby 的一些语法上的灵活性。

Ruby 支持代码块、修饰符等这些在其他语言里似乎都没有，最简单的示例：

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;

&lt;span class=&quot;vg&quot;&gt;$debug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;debug&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$debug&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

新建了一个 Ruby 的笔记仓库，用来记录 Ruby 学习资料。

https://github.com/wsdjeg/ruby-tutorial-cn
</description>
        <pubDate>Thu, 09 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/initial-knowledge-of-ruby/</link>
        <guid isPermaLink="true">https://wsdjeg.net/initial-knowledge-of-ruby/</guid>
        
        <category>ruby</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Vim 中文文档规范检查插件</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#初心&quot; id=&quot;markdown-toc-初心&quot;&gt;初心&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#使用说明&quot; id=&quot;markdown-toc-使用说明&quot;&gt;使用说明&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#协作开发&quot; id=&quot;markdown-toc-协作开发&quot;&gt;协作开发&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;初心&quot;&gt;初心&lt;/h2&gt;

经常使用 markdown 进行中文写作，包括但不限于写一些文档。对于中文排版目前没有非常好的检查工具。
因此做了 chinese_linter.vim 这个插件，目的在于提示中文文档中一些常见的排版错误。

&lt;h2 id=&quot;使用说明&quot;&gt;使用说明&lt;/h2&gt;

在编辑中文文档时，使用如下命令即可检查，错误信息将被展示在 Vim 的 location list 窗口

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:CheckChinese
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

目前支持如下错误代码：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;错误代码&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;E001&lt;/td&gt;
      &lt;td&gt;中文字符后存在英文标点&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;E002&lt;/td&gt;
      &lt;td&gt;中英文之间没有空格&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;E003&lt;/td&gt;
      &lt;td&gt;中文与数字之间没有空格&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;E004&lt;/td&gt;
      &lt;td&gt;中文标点之后存在空格&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;E005&lt;/td&gt;
      &lt;td&gt;行尾含有空格&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

该插件才开始做，目前仅仅实现了以上五种规范检查，后面会添加更多的规范检查，欢迎尝试。

&lt;h2 id=&quot;协作开发&quot;&gt;协作开发&lt;/h2&gt;

目前这个项目发布在 github 上面，如果有熟悉 Vim 脚本的同学，也欢迎参与，感谢！

&lt;a href=&quot;https://github.com/wsdjeg/ChineseLinter.vim&quot;&gt;wsdjeg/ChineseLinter.vim&lt;/a&gt;
</description>
        <pubDate>Wed, 01 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/vim-chinese-linter/</link>
        <guid isPermaLink="true">https://wsdjeg.net/vim-chinese-linter/</guid>
        
        <category>vim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>为什么要学习 Vim？</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#vim-的特点&quot; id=&quot;markdown-toc-vim-的特点&quot;&gt;Vim 的特点&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

接触过好几种编辑器、IDE，最终感觉还是 Vim 最适合。
学会了 Vim 之后，几乎没有任何动力去换其他编辑器（ Neovim 除外）。
相信有很多 Vim 用户和我一样，对 Vim 存在这种感觉。

&lt;h2 id=&quot;vim-的特点&quot;&gt;Vim 的特点&lt;/h2&gt;

&lt;strong&gt;极简的思想&lt;/strong&gt;

其实，Vim 代表的是一种 KISS 的 Geek 思想，而不仅仅是炫耀。这种思想是指：“选择你需要的，舍弃那些你不需要的”， 一种极简思想。一个臃肿的工具，也许可以提供 100% 的功能，但是，实际上你只需要 10% 的功能，其余 90% 功能， 你可能都没有心思去研究。那为什么不丢弃臃肿的 90%，轻装上阵呢？

当然，适当的展示，活跃社区气氛，吸引新人入坑 Vim 是我辈使命。

&lt;strong&gt;Vim 模式&lt;/strong&gt;

Vim 不同于其他编辑器的地方，就是她提供的模式化编辑，和文本对象。任何 IDE 或者编辑器模拟的 Vim 插件， 无非是实现了这两个功能。通过模式，Vim 赋予了同一个按键多种功能，大大提高了按键的功效，可以让我们双手 集中在键盘中央区域，提高效率。另外，Vim 将一切文本看成对象，比如删除一个单词，diw（ delete in word ） 等等这一类用法，我可以理解为 Vim 语。

记得以前看过一段文字，大致内容是这样的：

你只有折腾 Vim 累死过 3 次，你才能真正的喜欢上它，不然你就会选择放弃，最终回到 IDE。 在 Vim 的世界里，一切都需要自己动手，所以，他不适合不喜欢折腾的人，如果你对它没有 200% 的好奇心，不要玩， 不然你一定会摔键盘.

为什么说 Vim 写代码快？ 前提你累死过 3 次，成功配置了 Vim。

那么开始神奇的 Vim 之旅。你就发现:

&lt;ul&gt;
  &lt;li&gt;你删代码比队友快: “first blood”&lt;/li&gt;
  &lt;li&gt;自动补全比队友快&lt;/li&gt;
  &lt;li&gt;在 20 个 G 的文件堆里定位代码各种秒杀你队友&lt;/li&gt;
  &lt;li&gt;在 vim 中完成各种 shell， 秒杀你队友 “ Killing spree ”!&lt;/li&gt;
  &lt;li&gt;优雅的更新升级， 删除 Vim 插件（前提 Vundle ） “ Dominating ”!&lt;/li&gt;
  &lt;li&gt;随性的自定义快捷键，完全属于你自己的风格， 一个配置文件随身带着走。或者压缩 Vim 文件包带着走， 想去哪就去哪，不用等你队友带节奏。Unstoppable ！&lt;/li&gt;
  &lt;li&gt;你队友还在用鼠标？那你已经进化了 。Wicked Sick ！！&lt;/li&gt;
  &lt;li&gt;什么？ 开始用 Vim Markdown 来写文档了？ 我草，你已经超神了！！ God Like ！！！&lt;/li&gt;
  &lt;li&gt;你已经离不开 Vim 了。 从最开始被各种折腾到想要砸键盘的你， 如今你已经爱上他了。aM-m-m-m….（重复 8 次） Monster Kill&lt;/li&gt;
  &lt;li&gt;你注定和 Vim 过完这一生！……Holy Shit&lt;/li&gt;
&lt;/ul&gt;

于是你开始对自己以前的一些行为出现质疑：

&lt;ul&gt;
  &lt;li&gt;删除一行 dd 不就行了，为什么要鼠标选中一行之后按下 backspace ？&lt;/li&gt;
  &lt;li&gt;清除一行内容 S 不就行了，为什么还要鼠标选中一行然后按下 backspace ？&lt;/li&gt;
  &lt;li&gt;给一行末尾补分号 A; 不就好了，为什么还要鼠标移过去末尾点一下然后按下;？&lt;/li&gt;
  &lt;li&gt;然后给 n 行末尾补分号，VNj 选中多行 :normal .（点可以重复上次操作）不就好了，为什么要鼠标一个一个点了然后一个个补？&lt;/li&gt;
  &lt;li&gt;复制 a 行插入到 b 行后，dd 掉 a 行在 b 行那按下 p 不就好了。 为什么要鼠标选中 a，ctrl+x，然后到 b 的末尾按下回车，然后 ctrl-v ？&lt;/li&gt;
&lt;/ul&gt;

所以，同为喜欢 Vim 的你，让我们一起来说 Vim 语吧!
</description>
        <pubDate>Sun, 25 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/why-study-vim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/why-study-vim/</guid>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Vim 下多光标编辑 iedit 模式</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#什么是-iedit-模式&quot; id=&quot;markdown-toc-什么是-iedit-模式&quot;&gt;什么是 iedit 模式&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#如何启动-iedit-模式&quot; id=&quot;markdown-toc-如何启动-iedit-模式&quot;&gt;如何启动 iedit 模式&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#iedit-模式模式快捷键&quot; id=&quot;markdown-toc-iedit-模式模式快捷键&quot;&gt;iedit 模式模式快捷键&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;blockquote&gt;
  原文链接：https://blog.csdn.net/wsdjeg/article/details/79138641
&lt;/blockquote&gt;

&lt;h2 id=&quot;什么是-iedit-模式&quot;&gt;什么是 iedit 模式&lt;/h2&gt;

iedit 模式是 SpaceVim 中最新实现的一个多光标编辑模式，取名 iedit 借鉴了 emacs 的 iedit-mode，这一模式给 vim 增添了多光标编辑功能。

效果图如下：

&lt;img src=&quot;../images/iedit-mode.gif&quot; alt=&quot;&quot; /&gt;

&lt;h2 id=&quot;如何启动-iedit-模式&quot;&gt;如何启动 iedit 模式&lt;/h2&gt;

在 SpaceVim 中有三种方式启动 iedit 模式：

&lt;ul&gt;
  &lt;li&gt;Normal 模式下直接按下快捷键 SPC s e 会匹配光标所在的单词，并启动 iedit 模式。&lt;/li&gt;
  &lt;li&gt;Visual 模式下按下快捷键 SPC s e 会匹配所选择的单词，并启动 iedit 模式。&lt;/li&gt;
  &lt;li&gt;Highlight Symbol 模式按下 e 键会更具以选择的匹配位置来启动 iedit 模式。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;iedit-模式模式快捷键&quot;&gt;iedit 模式模式快捷键&lt;/h2&gt;

模式转变:

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Key Binding&lt;/th&gt;
      &lt;th&gt;From&lt;/th&gt;
      &lt;th&gt;to&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPC s e&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;normal or visual&lt;/td&gt;
      &lt;td&gt;iedit-Normal&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

iedit-Normal 模式快捷键:

iedit-Normal 模式模仿 vim Normal 模式，以下的这些快捷键仅限于 iedit-Normal 模式.

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Key Binding&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Esc&lt;/td&gt;
      &lt;td&gt;go back to Normal mode&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;i&lt;/td&gt;
      &lt;td&gt;switch to iedit-Insert mode, same as i&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;a&lt;/td&gt;
      &lt;td&gt;switch to iedit-Insert mode, same as a&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;I&lt;/td&gt;
      &lt;td&gt;go to the beginning of the current occurrence and switch to iedit-Insert mode&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;A&lt;/td&gt;
      &lt;td&gt;go to the end of the current occurrence and switch to iedit-Insert mode&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;Left&gt;&lt;/Left&gt;&lt;/td&gt;
      &lt;td&gt;Move cursor to left&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;Right&gt;&lt;/Right&gt;&lt;/td&gt;
      &lt;td&gt;Move cursor to right&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;go to the beginning of the current occurrence&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$&lt;/td&gt;
      &lt;td&gt;go to the end of the current occurrence&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;D&lt;/td&gt;
      &lt;td&gt;delete the occurrences&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;S&lt;/td&gt;
      &lt;td&gt;delete the occurrences and switch to iedit-Insert mode&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;gg&lt;/td&gt;
      &lt;td&gt;go to first occurrence&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;G&lt;/td&gt;
      &lt;td&gt;go to last occurrence&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;n&lt;/td&gt;
      &lt;td&gt;go to next occurrence&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;N&lt;/td&gt;
      &lt;td&gt;go to previous occurrence&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

iedit-Insert 模式快捷键:

iedit-Insert 模式借鉴与 vim Insert 模式下的快捷键，也借鉴了 emacs 和 bash 命令行下的快捷键：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Key Binding&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Esc&lt;/td&gt;
      &lt;td&gt;go back to iedit-Normal mode&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;Left&gt;&lt;/Left&gt;&lt;/td&gt;
      &lt;td&gt;Move cursor to left&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;Right&gt;&lt;/Right&gt;&lt;/td&gt;
      &lt;td&gt;Move cursor to right&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;C-w&gt;&lt;/C-w&gt;&lt;/td&gt;
      &lt;td&gt;delete words before cursor&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;C-K&gt;&lt;/C-K&gt;&lt;/td&gt;
      &lt;td&gt;delete words after cursor&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</description>
        <pubDate>Tue, 23 Jan 2018 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/iedit-mode-for-neovim-and-vim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/iedit-mode-for-neovim-and-vim/</guid>
        
        <category>vim</category>
        
        <category>neovim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Vim 从入门到精通</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#简介&quot; id=&quot;markdown-toc-简介&quot;&gt;简介&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#什么是-vim&quot; id=&quot;markdown-toc-什么是-vim&quot;&gt;什么是 Vim？&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#vim-哲学&quot; id=&quot;markdown-toc-vim-哲学&quot;&gt;Vim 哲学&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#入门&quot; id=&quot;markdown-toc-入门&quot;&gt;入门&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#精简的-vimrc&quot; id=&quot;markdown-toc-精简的-vimrc&quot;&gt;精简的 vimrc&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#windows-系统&quot; id=&quot;markdown-toc-windows-系统&quot;&gt;Windows 系统&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#linux-或者-mac-os&quot; id=&quot;markdown-toc-linux-或者-mac-os&quot;&gt;Linux 或者 Mac OS&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#我正在使用什么样的-vim&quot; id=&quot;markdown-toc-我正在使用什么样的-vim&quot;&gt;我正在使用什么样的 Vim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#备忘录&quot; id=&quot;markdown-toc-备忘录&quot;&gt;备忘录&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#基础&quot; id=&quot;markdown-toc-基础&quot;&gt;基础&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#缓冲区窗口标签&quot; id=&quot;markdown-toc-缓冲区窗口标签&quot;&gt;缓冲区，窗口，标签&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#已激活已载入已列出已命名的缓冲区&quot; id=&quot;markdown-toc-已激活已载入已列出已命名的缓冲区&quot;&gt;已激活、已载入、已列出、已命名的缓冲区&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#参数列表&quot; id=&quot;markdown-toc-参数列表&quot;&gt;参数列表&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#按键映射&quot; id=&quot;markdown-toc-按键映射&quot;&gt;按键映射&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#映射前置键&quot; id=&quot;markdown-toc-映射前置键&quot;&gt;映射前置键&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#寄存器&quot; id=&quot;markdown-toc-寄存器&quot;&gt;寄存器&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#范围&quot; id=&quot;markdown-toc-范围&quot;&gt;范围&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#标注&quot; id=&quot;markdown-toc-标注&quot;&gt;标注&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#补全&quot; id=&quot;markdown-toc-补全&quot;&gt;补全&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#动作操作符文本对象&quot; id=&quot;markdown-toc-动作操作符文本对象&quot;&gt;动作，操作符，文本对象&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#自动命令&quot; id=&quot;markdown-toc-自动命令&quot;&gt;自动命令&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#变更历史跳转历史&quot; id=&quot;markdown-toc-变更历史跳转历史&quot;&gt;变更历史，跳转历史&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#内容变更历史记录&quot; id=&quot;markdown-toc-内容变更历史记录&quot;&gt;内容变更历史记录&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#全局位置信息表局部位置信息表&quot; id=&quot;markdown-toc-全局位置信息表局部位置信息表&quot;&gt;全局位置信息表，局部位置信息表&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#宏&quot; id=&quot;markdown-toc-宏&quot;&gt;宏&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#颜色主题&quot; id=&quot;markdown-toc-颜色主题&quot;&gt;颜色主题&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#折叠&quot; id=&quot;markdown-toc-折叠&quot;&gt;折叠&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#会话&quot; id=&quot;markdown-toc-会话&quot;&gt;会话&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#局部化&quot; id=&quot;markdown-toc-局部化&quot;&gt;局部化&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#用法&quot; id=&quot;markdown-toc-用法&quot;&gt;用法&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#获取离线帮助&quot; id=&quot;markdown-toc-获取离线帮助&quot;&gt;获取离线帮助&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#获取离线帮助补充&quot; id=&quot;markdown-toc-获取离线帮助补充&quot;&gt;获取离线帮助（补充）&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#获取在线帮助&quot; id=&quot;markdown-toc-获取在线帮助&quot;&gt;获取在线帮助&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#执行自动命令&quot; id=&quot;markdown-toc-执行自动命令&quot;&gt;执行自动命令&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#用户自定义事件&quot; id=&quot;markdown-toc-用户自定义事件&quot;&gt;用户自定义事件&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#事件嵌套&quot; id=&quot;markdown-toc-事件嵌套&quot;&gt;事件嵌套&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#剪切板&quot; id=&quot;markdown-toc-剪切板&quot;&gt;剪切板&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#剪贴板的使用windows-osx&quot; id=&quot;markdown-toc-剪贴板的使用windows-osx&quot;&gt;剪贴板的使用（Windows, OSX）&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#剪贴板的使用linux-bsd-&quot; id=&quot;markdown-toc-剪贴板的使用linux-bsd-&quot;&gt;剪贴板的使用（Linux, BSD, …）&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#打开文件时恢复光标位置&quot; id=&quot;markdown-toc-打开文件时恢复光标位置&quot;&gt;打开文件时恢复光标位置&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#临时文件&quot; id=&quot;markdown-toc-临时文件&quot;&gt;临时文件&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#备份文件&quot; id=&quot;markdown-toc-备份文件&quot;&gt;备份文件&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#交换文件&quot; id=&quot;markdown-toc-交换文件&quot;&gt;交换文件&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#撤销文件&quot; id=&quot;markdown-toc-撤销文件&quot;&gt;撤销文件&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#viminfo-文件&quot; id=&quot;markdown-toc-viminfo-文件&quot;&gt;viminfo 文件&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#临时文件管理设置示例&quot; id=&quot;markdown-toc-临时文件管理设置示例&quot;&gt;临时文件管理设置示例&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#编辑远程文件&quot; id=&quot;markdown-toc-编辑远程文件&quot;&gt;编辑远程文件&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#插件管理&quot; id=&quot;markdown-toc-插件管理&quot;&gt;插件管理&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#多行编辑&quot; id=&quot;markdown-toc-多行编辑&quot;&gt;多行编辑&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#使用外部程序和过滤器&quot; id=&quot;markdown-toc-使用外部程序和过滤器&quot;&gt;使用外部程序和过滤器&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#cscope&quot; id=&quot;markdown-toc-cscope&quot;&gt;Cscope&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#1-构建数据库&quot; id=&quot;markdown-toc-1-构建数据库&quot;&gt;1. 构建数据库&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#2-添加数据库&quot; id=&quot;markdown-toc-2-添加数据库&quot;&gt;2. 添加数据库&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#3-查询数据库&quot; id=&quot;markdown-toc-3-查询数据库&quot;&gt;3. 查询数据库&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#matchit&quot; id=&quot;markdown-toc-matchit&quot;&gt;MatchIt&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#在-vim-8-中安装&quot; id=&quot;markdown-toc-在-vim-8-中安装&quot;&gt;在 Vim 8 中安装&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#在-vim-7-或者更早的版本中安装&quot; id=&quot;markdown-toc-在-vim-7-或者更早的版本中安装&quot;&gt;在 Vim 7 或者更早的版本中安装&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#简短的介绍&quot; id=&quot;markdown-toc-简短的介绍&quot;&gt;简短的介绍&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#技巧&quot; id=&quot;markdown-toc-技巧&quot;&gt;技巧&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#跳至选择的区域另一端&quot; id=&quot;markdown-toc-跳至选择的区域另一端&quot;&gt;跳至选择的区域另一端&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#聪明地使用-n-和-n&quot; id=&quot;markdown-toc-聪明地使用-n-和-n&quot;&gt;聪明地使用 n 和 N&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#聪明地使用命令行历史&quot; id=&quot;markdown-toc-聪明地使用命令行历史&quot;&gt;聪明地使用命令行历史&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#智能-ctrl-l&quot; id=&quot;markdown-toc-智能-ctrl-l&quot;&gt;智能 Ctrl-l&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#禁用错误报警声音和图标&quot; id=&quot;markdown-toc-禁用错误报警声音和图标&quot;&gt;禁用错误报警声音和图标&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#快速移动当前行&quot; id=&quot;markdown-toc-快速移动当前行&quot;&gt;快速移动当前行&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#快速添加空行&quot; id=&quot;markdown-toc-快速添加空行&quot;&gt;快速添加空行&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#运行时检测&quot; id=&quot;markdown-toc-运行时检测&quot;&gt;运行时检测&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#查看启动时间&quot; id=&quot;markdown-toc-查看启动时间&quot;&gt;查看启动时间&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#nul-符用新行表示&quot; id=&quot;markdown-toc-nul-符用新行表示&quot;&gt;NUL 符用新行表示&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#快速编辑自定义宏&quot; id=&quot;markdown-toc-快速编辑自定义宏&quot;&gt;快速编辑自定义宏&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#快速跳转到源头文件&quot; id=&quot;markdown-toc-快速跳转到源头文件&quot;&gt;快速跳转到源(头)文件&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#在-gui-中快速改变字体大小&quot; id=&quot;markdown-toc-在-gui-中快速改变字体大小&quot;&gt;在 GUI 中快速改变字体大小&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#根据模式改变光标类型&quot; id=&quot;markdown-toc-根据模式改变光标类型&quot;&gt;根据模式改变光标类型&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#防止水平滑动的时候失去选择&quot; id=&quot;markdown-toc-防止水平滑动的时候失去选择&quot;&gt;防止水平滑动的时候失去选择&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#选择当前行至结尾排除换行符&quot; id=&quot;markdown-toc-选择当前行至结尾排除换行符&quot;&gt;选择当前行至结尾，排除换行符&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#重新载入保存文件&quot; id=&quot;markdown-toc-重新载入保存文件&quot;&gt;重新载入保存文件&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#更加智能的当前行高亮&quot; id=&quot;markdown-toc-更加智能的当前行高亮&quot;&gt;更加智能的当前行高亮&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#更快的关键字补全&quot; id=&quot;markdown-toc-更快的关键字补全&quot;&gt;更快的关键字补全&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#改变颜色主题的默认外观&quot; id=&quot;markdown-toc-改变颜色主题的默认外观&quot;&gt;改变颜色主题的默认外观&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#命令&quot; id=&quot;markdown-toc-命令&quot;&gt;命令&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#global-和-vglobal---在所有匹配行执行命令&quot; id=&quot;markdown-toc-global-和-vglobal---在所有匹配行执行命令&quot;&gt;:global 和 :vglobal - 在所有匹配行执行命令&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#normal-和-execute---脚本梦之队&quot; id=&quot;markdown-toc-normal-和-execute---脚本梦之队&quot;&gt;:normal 和 :execute - 脚本梦之队&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#重定向消息&quot; id=&quot;markdown-toc-重定向消息&quot;&gt;重定向消息&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#调试&quot; id=&quot;markdown-toc-调试&quot;&gt;调试&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#常规建议&quot; id=&quot;markdown-toc-常规建议&quot;&gt;常规建议&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#调整日志等级&quot; id=&quot;markdown-toc-调整日志等级&quot;&gt;调整日志等级&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#查看启动日志&quot; id=&quot;markdown-toc-查看启动日志&quot;&gt;查看启动日志&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#查看运行时日志&quot; id=&quot;markdown-toc-查看运行时日志&quot;&gt;查看运行时日志&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#vim-脚本调试&quot; id=&quot;markdown-toc-vim-脚本调试&quot;&gt;Vim 脚本调试&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#语法文件调试&quot; id=&quot;markdown-toc-语法文件调试&quot;&gt;语法文件调试&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#杂项&quot; id=&quot;markdown-toc-杂项&quot;&gt;杂项&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#附加资源&quot; id=&quot;markdown-toc-附加资源&quot;&gt;附加资源&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#vim-配置集合&quot; id=&quot;markdown-toc-vim-配置集合&quot;&gt;Vim 配置集合&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#常见问题&quot; id=&quot;markdown-toc-常见问题&quot;&gt;常见问题&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#编辑小文件时很慢&quot; id=&quot;markdown-toc-编辑小文件时很慢&quot;&gt;编辑小文件时很慢&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#编辑大文件的时候很慢&quot; id=&quot;markdown-toc-编辑大文件的时候很慢&quot;&gt;编辑大文件的时候很慢&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#持续粘贴为什么我每次都要设置-paste-模式&quot; id=&quot;markdown-toc-持续粘贴为什么我每次都要设置-paste-模式&quot;&gt;持续粘贴（为什么我每次都要设置 ‘paste’ 模式）&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#在终端中按-esc-后有延时&quot; id=&quot;markdown-toc-在终端中按-esc-后有延时&quot;&gt;在终端中按 ESC 后有延时&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#无法重复函数中执行的搜索&quot; id=&quot;markdown-toc-无法重复函数中执行的搜索&quot;&gt;无法重复函数中执行的搜索&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;blockquote&gt;
  本文翻译自：&lt;a href=&quot;https://github.com/mhinz/vim-galore&quot;&gt;mhinz/vim-galore&lt;/a&gt;, 部分内容有增改。
&lt;/blockquote&gt;

&lt;h2 id=&quot;简介&quot;&gt;简介&lt;/h2&gt;

&lt;h3 id=&quot;什么是-vim&quot;&gt;什么是 Vim？&lt;/h3&gt;

&lt;a href=&quot;https://github.com/vim/vim&quot;&gt;Vim&lt;/a&gt; 是一个历史悠久的文本编辑器，可以追溯到
&lt;a href=&quot;https://en.wikipedia.org/wiki/QED_(text_editor)&quot;&gt;qed&lt;/a&gt;。
&lt;a href=&quot;https://en.wikipedia.org/wiki/Bram_Moolenaar&quot;&gt;Bram Moolenaar&lt;/a&gt; 于
1991 年发布初始版本。

Linux、Mac 用户，可以使用包管理器安装 Vim，对于 Windows 用户，可以使用 scoop 包管理器进行下载安装。
该版本可轻易添加 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python&lt;/code&gt; 、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python3&lt;/code&gt; 、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lua&lt;/code&gt; 等支持，只需要安装 python、lua
即可。

项目在 &lt;a href=&quot;https://github.com/vim/vim&quot;&gt;Github&lt;/a&gt; 上开发，项目讨论请订阅
&lt;a href=&quot;https://groups.google.com/forum/#!forum/vim_dev&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim_dev&lt;/code&gt;&lt;/a&gt; 邮件列表。

通过阅读 &lt;a href=&quot;http://www.viemu.com/a-why-vi-vim.html&quot;&gt;Why, oh WHY, do those #?@! nutheads use vi?&lt;/a&gt;
来对 Vim 进行大致的了解。

&lt;h3 id=&quot;vim-哲学&quot;&gt;Vim 哲学&lt;/h3&gt;

Vim 采用模式编辑的理念，即它提供了多种模式，按键在不同的模式下作用不同。
你可以在&lt;strong&gt;普通模式&lt;/strong&gt; 下浏览文件，在&lt;strong&gt;插入模式&lt;/strong&gt;下插入文本，
在&lt;strong&gt;可视模式&lt;/strong&gt;下选择行，在&lt;strong&gt;命令模式&lt;/strong&gt;下执行命令等等。起初这听起来可能很复杂，
但是这有一个很大的优点：不需要通过同时按住多个键来完成操作，
大多数时候你只需要依次按下这些按键即可。越常用的操作，所需要的按键数量越少。

和模式编辑紧密相连的概念是 &lt;strong&gt;操作符&lt;/strong&gt; 和 &lt;strong&gt;动作&lt;/strong&gt;。&lt;strong&gt;操作符&lt;/strong&gt; 指的是开始某个行为，
例如：修改、删除或者选择文本，之后你要用一个 &lt;strong&gt;动作&lt;/strong&gt; 来指定需要操作的文本区域。
比如，要改变括号内的文本，需要执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ci(&lt;/code&gt; （读做 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;change inner parentheses&lt;/code&gt;）；
删除整个段落的内容，需要执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dap&lt;/code&gt; （读做：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delete around paragraph&lt;/code&gt;）。

如果你能看见 Vim 老司机操作，你会发现他们使用 Vim 脚本语言就如同钢琴师弹钢琴一样。
复杂的操作只需要几个按键就能完成。他们甚至不用刻意去想，因为这已经成为&lt;a href=&quot;https://en.wikipedia.org/wiki/Muscle_memory&quot;&gt;肌肉记忆&lt;/a&gt;了。
这减少&lt;a href=&quot;https://en.wikipedia.org/wiki/Cognitive_load&quot;&gt;认识负荷&lt;/a&gt;并帮助人们专注于实际任务。

&lt;h3 id=&quot;入门&quot;&gt;入门&lt;/h3&gt;

Vim 自带一个交互式的教程，内含你需要了解的最基础的信息，你可以通过终端运行以下命令打开教程：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ vimtutor
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

不要因为这个看上去很无聊而跳过，按照此教程多练习。你以前用的 IDE 或者其他编辑器很少是有“模式”概念的，
因此一开始你会很难适应模式切换。但是你 Vim 使用的越多，&lt;a href=&quot;https://en.wikipedia.org/wiki/Muscle_memory&quot;&gt;肌肉记忆&lt;/a&gt; 将越容易形成。

Vim 基于一个 &lt;a href=&quot;https://en.wikipedia.org/wiki/Vi&quot;&gt;vi&lt;/a&gt; 克隆，叫做 &lt;a href=&quot;https://en.wikipedia.org/wiki/Stevie_(text_editor)&quot;&gt;Stevie&lt;/a&gt;，
支持两种运行模式：”compatible” 和 “nocompatible”。在兼容模式下运行 Vim 意味着使用 vi 的默认设置，
而不是 Vim 的默认设置。除非你新建一个用户的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vimrc&lt;/code&gt; 或者使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim -N&lt;/code&gt; 命令启动 Vim，
否则就是在兼容模式下运行 Vim！请大家不要在兼容模式下运行 Vim。

下一步

&lt;ol&gt;
  &lt;li&gt;创建你自己的 &lt;a href=&quot;#精简的-vimrc&quot;&gt;vimrc&lt;/a&gt;。&lt;/li&gt;
  &lt;li&gt;在第一周准备&lt;a href=&quot;#备忘录&quot;&gt;备忘录&lt;/a&gt;。&lt;/li&gt;
  &lt;li&gt;通读&lt;a href=&quot;#基础-1&quot;&gt;基础&lt;/a&gt;章节了解 Vim 还有哪些功能。&lt;/li&gt;
  &lt;li&gt;按需学习！Vim 是学不完的。如果你遇到了问题，先上网寻找解决方案，你的问题可能已经被解决了。Vim 拥有大量的参考文档，知道如何利用这些参考文档很有必要：&lt;a href=&quot;#获取离线帮助&quot;&gt;获取离线帮助&lt;/a&gt;。&lt;/li&gt;
  &lt;li&gt;浏览&lt;a href=&quot;#附加资源&quot;&gt;附加资源&lt;/a&gt;。&lt;/li&gt;
&lt;/ol&gt;

最后一个建议：使用&lt;a href=&quot;#插件管理&quot;&gt;插件&lt;/a&gt;之前，请先掌握 Vim 的基本操作。很多插件都只是对 Vim 自带功能的封装。

&lt;h3 id=&quot;精简的-vimrc&quot;&gt;精简的 vimrc&lt;/h3&gt;

Vim 启动是会按照一定的优先顺序来搜索配置文件，这个顺序，可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:version&lt;/code&gt; 命令查看。下面分 Windows 系统，
和 *niux 系统分别来说明 Vim 是如何载入配置文件的。

&lt;h4 id=&quot;windows-系统&quot;&gt;Windows 系统&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   system vimrc file: &quot;$VIM\vimrc&quot;
     user vimrc file: &quot;$HOME\_vimrc&quot;
 2nd user vimrc file: &quot;$HOME\vimfiles\vimrc&quot;
 3rd user vimrc file: &quot;$VIM\_vimrc&quot;
      user exrc file: &quot;$HOME\_exrc&quot;
  2nd user exrc file: &quot;$VIM\_exrc&quot;
  system gvimrc file: &quot;$VIM\gvimrc&quot;
    user gvimrc file: &quot;$HOME\_gvimrc&quot;
2nd user gvimrc file: &quot;$HOME\vimfiles\gvimrc&quot;
3rd user gvimrc file: &quot;$VIM\_gvimrc&quot;
       defaults file: &quot;$VIMRUNTIME\defaults.vim&quot;
    system menu file: &quot;$VIMRUNTIME\menu.vim&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

我们只看上面这一段，Vim 会优先读取 user vimrc file: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME\_vimrc&lt;/code&gt;, 当这一文件不存在是，
Vim 再去寻找 2nd user vimrc file: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME\vimfiles\vimrc&lt;/code&gt;; 倘若这个文件还是不存在，那么 Vim
会去继续寻找 3rd user vimrc file: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$VIM\_vimrc&lt;/code&gt;。 了解以上顺序后，就不会再因为 Vim
总是不读取配置文件而感到烦恼了。

&lt;h4 id=&quot;linux-或者-mac-os&quot;&gt;Linux 或者 Mac OS&lt;/h4&gt;

同 Windows 系统类似，也可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:version&lt;/code&gt; 命令查看 vim 载入配置的优先顺序。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     系统 vimrc 文件: &quot;/etc/vimrc&quot;
     用户 vimrc 文件: &quot;$HOME/.vimrc&quot;
 第二用户 vimrc 文件: &quot;~/.vim/vimrc&quot;
      用户 exrc 文件: &quot;$HOME/.exrc&quot;
       defaults file: &quot;$VIMRUNTIME/defaults.vim&quot;
         $VIM 预设值: &quot;/etc&quot;
  $VIMRUNTIME 预设值: &quot;/usr/share/vim/vim81&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

你可以在网上找到许多精简的 vimrc 配置文件，我的版本可能并不是最简单的版本，但是我的版本提供了一套我认为良好的，非常适合入门的设置。

最终你需要阅读完那些设置，然后自行决定需要使用哪些。:-)

精简的 vimrc 地址：&lt;a href=&quot;https://github.com/wsdjeg/vim-galore-zh_cn/blob/master/contents/minimal-vimrc.vim&quot;&gt;minimal-vimrc&lt;/a&gt;

如果你有兴趣，这里是我（原作者）的 &lt;a href=&quot;https://github.com/mhinz/dotfiles/blob/master/.vim/vimrc&quot;&gt;vimrc&lt;/a&gt;。

&lt;strong&gt;建议&lt;/strong&gt;：大多数插件作者都维护不止一个插件并且将他们的 vimrc 放在 Github 上展示（通常放在叫做 “vim-config” 或者 “dotfiles” 的仓库中），所以当你发现你喜欢的插件时，去插件维护者的 Github 主页看看有没有这样的仓库。

&lt;h3 id=&quot;我正在使用什么样的-vim&quot;&gt;我正在使用什么样的 Vim&lt;/h3&gt;

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:version&lt;/code&gt; 命令将向你展示当前正在运行的 Vim 的所有相关信息，包括它是如何编译的。

第一行告诉你这个二进制文件的编译时间和版本号，比如：7.4。接下来的一行呈现 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Included patches: 1-1051&lt;/code&gt;，这是补丁版本包。因此你 Vim 确切的版本号是 7.4.1051。

另一行显示着一些像 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tiny version without GUI&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Huge version with GUI&lt;/code&gt; 的信息。很显然这些信息告诉你当前的 Vim 是否支持 GUI，例如：从终端中运行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gvim&lt;/code&gt; 或者从终端模拟器中的 Vim 内运行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:gui&lt;/code&gt; 命令。另一个重要的信息是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tiny&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Huge&lt;/code&gt;。Vim 的特性集区分被叫做 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tiny&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;small&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;normal&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;big&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;huge&lt;/code&gt;，所有的都实现不同的功能子集。

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:version&lt;/code&gt; 主要的输出内容是特性列表。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+clipboard&lt;/code&gt; 意味这剪贴板功能被编译支持了，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-clipboard&lt;/code&gt; 意味着剪贴板特性没有被编译支持。

一些功能特性需要编译支持才能正常工作。例如：为了让 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:prof&lt;/code&gt; 工作，你需要使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;huge&lt;/code&gt; 模式编译的 Vim，因为那种模式启用了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+profile&lt;/code&gt; 特性。

如果你的输出情况并不是那样，并且你是从包管理器安装 Vim 的，确保你安装了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim-x&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim-x11&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim-gtk&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim-gnome&lt;/code&gt; 这些包或者相似的，因为这些包通常都是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;huge&lt;/code&gt; 模式编译的。

你也可以运行下面这段代码来测试 Vim 版本以及功能支持：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot; Do something if running at least Vim 7.4.42 with +profile enabled.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;704&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;704&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;nb&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;patch42&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;nb&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;profile&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&quot; do stuff&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

相关帮助：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:h :version
:h feature-list
:h +feature-list
:h has-patch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;备忘录&quot;&gt;备忘录&lt;/h3&gt;

为了避免版权问题，我只贴出链接：

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://people.csail.mit.edu/vgod/vim/vim-cheat-sheet-en.png&quot;&gt;http://people.csail.mit.edu/vgod/vim/vim-cheat-sheet-en.png&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cdn.shopify.com/s/files/1/0165/4168/files/preview.png&quot;&gt;https://cdn.shopify.com/s/files/1/0165/4168/files/preview.png&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.nathael.org/Data/vi-vim-cheat-sheet.svg&quot;&gt;http://www.nathael.org/Data/vi-vim-cheat-sheet.svg&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://michael.peopleofhonoronly.com/vim/vim_cheat_sheet_for_programmers_screen.png&quot;&gt;http://michael.peopleofhonoronly.com/vim/vim_cheat_sheet_for_programmers_screen.png&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.rosipov.com/images/posts/vim-movement-commands-cheatsheet.png&quot;&gt;http://www.rosipov.com/images/posts/vim-movement-commands-cheatsheet.png&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

或者在 Vim 中快速打开备忘录：&lt;a href=&quot;https://github.com/lifepillar/vim-cheat40&quot;&gt;vim-cheat40&lt;/a&gt;。

&lt;h2 id=&quot;基础&quot;&gt;基础&lt;/h2&gt;

&lt;h3 id=&quot;缓冲区窗口标签&quot;&gt;缓冲区，窗口，标签&lt;/h3&gt;

Vim 是一个文本编辑器。每次文本都是作为&lt;strong&gt;缓冲区&lt;/strong&gt;的一部分显示的。每一份文件都是在他们自己独有的缓冲区打开的，插件显示的内容也在它们自己的缓冲区中。

缓冲区有很多属性，比如这个缓冲区的内容是否可以修改，或者这个缓冲区是否和文件相关联，是否需要同步保存到磁盘上。

&lt;strong&gt;窗口&lt;/strong&gt; 是缓冲区上一层的视窗。如果你想同时查看几个文件或者查看同一文件的不同位置，那样你会需要窗口。

请别把他们叫做 &lt;em&gt;分屏&lt;/em&gt; 。你可以把一个窗口分割成两个，但是这并没有让这两个窗口完全 &lt;em&gt;分离&lt;/em&gt; 。

窗口可以水平或者竖直分割并且现有窗口的高度和宽度都是可以被调节设置的，因此，如果你需要多种窗口布局，请考虑使用标签。

&lt;strong&gt;标签页&lt;/strong&gt; （标签）是窗口的集合。因此当你想使用多种窗口布局时候请使用标签。

简单的说，如果你启动 Vim 的时候没有附带任何参数，你会得到一个包含着一个呈现一个缓冲区的窗口的标签。

顺带提一下，缓冲区列表是全局可见的，你可以在任何标签中访问任何一个缓冲区。

&lt;h3 id=&quot;已激活已载入已列出已命名的缓冲区&quot;&gt;已激活、已载入、已列出、已命名的缓冲区&lt;/h3&gt;

用类似 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim file1&lt;/code&gt; 的命令启动 Vim 。这个文件的内容将会被加载到缓冲区中，你现在有一个&lt;strong&gt;已载入的缓冲区&lt;/strong&gt;。如果你在 Vim 中保存这个文件，缓冲区内容将会被同步到磁盘上（写回文件中）。

由于这个缓冲区也在一个窗口上显示，所以他也是一个&lt;strong&gt;已激活的缓冲区&lt;/strong&gt;。如果你现在通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:e file2&lt;/code&gt; 命令加载另一个文件，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file1&lt;/code&gt; 将会变成一个&lt;strong&gt;隐藏的缓冲区&lt;/strong&gt;，并且 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file2&lt;/code&gt; 变成已激活缓冲区。

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:ls&lt;/code&gt; 我们能够列出所有可以列出的缓冲区。插件缓冲区和帮助缓冲区通常被标记为不可以列出的缓冲区，因为那并不是你经常需要在编辑器中编辑的常规文件。通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:ls!&lt;/code&gt; 命令可以显示被放入缓冲区列表的和未被放入列表的缓冲区。

&lt;strong&gt;未命名的缓冲区&lt;/strong&gt;是一种没有关联特定文件的缓冲区，这种缓冲区经常被插件使用。比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:enew&lt;/code&gt; 将会创建一个无名临时缓冲区。添加一些文本然后使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:w /tmp/foo&lt;/code&gt; 将他写入到磁盘，这样这个缓冲区就会变成一个&lt;strong&gt;已命名的缓冲区&lt;/strong&gt;。

&lt;h3 id=&quot;参数列表&quot;&gt;参数列表&lt;/h3&gt;

&lt;a href=&quot;#缓冲区窗口标签&quot;&gt;全局缓冲区列表&lt;/a&gt;是 Vim 的特性。在这之前的 vi 中，仅仅只有参数列表，参数列表在 Vim 中依旧可以使用。

每一个通过 shell 命令传递给 Vim 的文件名都被记录在一个参数列表中。可以有多个参数列表：默认情况下所有参数都被放在全局参数列表下，但是你可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:arglocal&lt;/code&gt; 命令去创建一个新的本地窗口的参数列表。

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:args&lt;/code&gt; 命令可以列出当前参数。使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:next&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:previous&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:first&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:last&lt;/code&gt; 命令可以在切换在参数列表中的文件。通过使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:argadd&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:argdelete&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:args&lt;/code&gt; 等命令加上一个文件列表可以改变参数列表。

偏爱缓冲区列表还是参数列表完全是个人选择，我的印象中大多数人都是使用缓冲区列表的。

然而参数列表在有些情况下被大量使用：批处理
使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:argdo&lt;/code&gt;！ 一个简单的重构例子：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;args&lt;/span&gt; **/*&lt;span class=&quot;p&quot;&gt;.[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;argdo&lt;/span&gt; %s&lt;span class=&quot;sr&quot;&gt;/foo/&lt;/span&gt;bar/ge &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;update&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这条命令将替换掉当前目录下以及当前目录的子目录中所有的 C 源文件和头文件中的“foo”，并用“bar”代替。

相关帮助：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h argument-list&lt;/code&gt;

&lt;h3 id=&quot;按键映射&quot;&gt;按键映射&lt;/h3&gt;

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:map&lt;/code&gt; 命令家族你可以定义属于你自己的快捷键。该家族的每一个命令都限定在特定的模式下。从技术上来说 Vim 自带高达 12 中模式，其中 6 种可以被映射。另外一些命令作用于多种模式：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;  递归  &lt;/th&gt;
      &lt;th&gt;  非递归    &lt;/th&gt;
      &lt;th&gt;模式                          &lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:map&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:noremap&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;normal, visual, operator-pending&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:nmap&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:nnoremap&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;normal&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:xmap&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:xnoremap&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;visual&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:cmap&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:cnoremap&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;command-line&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:omap&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:onoremap&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;operator-pending&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:imap&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:inoremap&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;insert&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

例如：这个自定义的快捷键只在普通模式下工作。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;nmap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;space&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;echo &lt;span class=&quot;s2&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:nunmap &amp;lt;space&amp;gt;&lt;/code&gt; 可以取消这个映射。

对于更少数，不常见的模式（或者他们的组合），查看 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h map-modes&lt;/code&gt;。

到现在为止还好，对新手而言有一个问题会困扰他们：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:nmap&lt;/code&gt; 是&lt;strong&gt;递归执行&lt;/strong&gt;的！结果是，右边执行可能的映射。

你自定义了一个简单的映射去输出“Foo”：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;nmap &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;echo &lt;span class=&quot;s2&quot;&gt;&quot;Foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

但是如果你想要映射 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; （回退一个单词）的默认功能到一个键上呢？

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;nmap &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果你敲击&lt;kbd&gt;a&lt;/kbd&gt;，我们期望着光标回退到上一个单词，但是实际情况是“Foo”被输出到命令行里！因为在右边，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; 已经被映射到别的行为上了，换句话说就是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:echo &quot;Foo&quot;&amp;lt;cr&amp;gt;&lt;/code&gt;。

解决此问题的正确方法是使用一种 &lt;em&gt;非递归&lt;/em&gt; 的映射代替：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;nnoremap &lt;span class=&quot;k&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

经验法则：除递归映射是必须的，否则总是使用非递归映射。

通过不给一个右值来检查你的映射。比如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:nmap&lt;/code&gt; 显示所以普通模式下的映射，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:nmap &amp;lt;leader&amp;gt;&lt;/code&gt; 显示所有以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;leader&amp;gt;&lt;/code&gt; 键开头的普通模式下的映射。

如果你想禁止用标准映射，把他们映射到特殊字符 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;nop&amp;gt;&lt;/code&gt; 上，例如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:noremap &amp;lt;left&amp;gt; &amp;lt;nop&amp;gt;&lt;/code&gt;。

相关帮助：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;notation
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; mapping
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;05&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;映射前置键&quot;&gt;映射前置键&lt;/h3&gt;

映射前置键（Leader 键）本身就是一个按键映射，默认为 &lt;kbd&gt;\\&lt;/kbd&gt;。我们可以通过在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; 中调用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;leader&amp;gt;&lt;/code&gt; 来为把它添加到其他按键映射中。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;helpgrep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;space&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这样，我们只需要先按 &lt;kbd&gt;\\&lt;/kbd&gt; 然后按 &lt;kbd&gt;h&lt;/kbd&gt; 就可以激活这个映射 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:helpgrep&amp;lt;space&amp;gt;&lt;/code&gt;。如果你想通过先按 &lt;kbd&gt;空格&lt;/kbd&gt; 键来触发，只需要这样做：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:mapleader&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;helpgrep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;space&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

此处建议使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g:mapleader&lt;/code&gt;，因为在 Vim 脚本中，函数外的变量缺省的作用域是全局变量，但是在函数内缺省作用域是局部变量，而设置快捷键前缀需要修改全局变量 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g:mapleader&lt;/code&gt; 的值。

另外，还有一个叫 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;localleader&amp;gt;&lt;/code&gt; 的，可以把它理解为局部环境中的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;leader&amp;gt;&lt;/code&gt;，默认值依然为 &lt;kbd&gt;\\&lt;/kbd&gt;。当我们需要只对某一个条件下（比如，特定文件类型的插件）的缓冲区设置特别的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;leader&amp;gt;&lt;/code&gt; 键，那么我们就可以通过修改当前环境下的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;localleader&amp;gt;&lt;/code&gt; 来实现。

&lt;strong&gt;注意&lt;/strong&gt;：如果你打算设置 Leader 键，请确保在设置按键映射之前，先设置好 Leader 键。如果你先设置了含有 Leader 键的映射，然后又修改了 Leader 键，那么之前映射内的 Leader 键是不会因此而改变的。你可以通过执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:nmap &amp;lt;leader&amp;gt;&lt;/code&gt; 来查看普通模式中已绑定给 Leader 键的所有映射。

请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h mapleader&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h maploacalleader&lt;/code&gt; 来获取更多帮助。

&lt;h3 id=&quot;寄存器&quot;&gt;寄存器&lt;/h3&gt;

寄存器就是存储文本的地方。我们常用的「复制」操作就是把文本存储到寄存器，「 粘贴」 操作就是把文本从寄存器中读出来。顺便，在 Vim 中复制的快捷键是 &lt;kbd&gt;y&lt;/kbd&gt;，粘贴的快捷键是 &lt;kbd&gt;p&lt;/kbd&gt;。

Vim 为我们提供了如下的寄存器：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;类型&lt;/th&gt;
      &lt;th&gt;标识&lt;/th&gt;
      &lt;th&gt;读写者&lt;/th&gt;
      &lt;th&gt;是否为只读&lt;/th&gt;
      &lt;th&gt;包含的字符来源&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Unnamed&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;vim&lt;/td&gt;
      &lt;td&gt;否&lt;/td&gt;
      &lt;td&gt;最近一次的复制或删除操作 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Numbered&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;至&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;vim&lt;/td&gt;
      &lt;td&gt;否&lt;/td&gt;
      &lt;td&gt;寄存器 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;: 最近一次复制。寄存器 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;: 最近一次删除。寄存器 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt;: 倒数第二次删除，以此类推。对于寄存器 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; 至 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9&lt;/code&gt;，他们其实是只读的最多包含 9 个元素的队列。这里的队列即为数据类型 &lt;a href=&quot;https://en.wikipedia.org/wiki/Queue_(abstract_data_type)&quot;&gt;queue&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Small delete&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;vim&lt;/td&gt;
      &lt;td&gt;否&lt;/td&gt;
      &lt;td&gt;最近一次行内删除&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Named&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt;至&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;z&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;至&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Z&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;用户&lt;/td&gt;
      &lt;td&gt;否&lt;/td&gt;
      &lt;td&gt;如果你通过复制操作存储文本至寄存器 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt;，那么 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; 中的文本就会被完全覆盖。如果你存储至 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;，那么会将文本添加给寄存器 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt;，不会覆盖之前已有的文本&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Read-only&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt;与&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;vim&lt;/td&gt;
      &lt;td&gt;是&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt;: 最近一次使用的命令，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt;: 最近一次添加的文本，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt;: 当前的文件名&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Alternate buffer&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;vim&lt;/td&gt;
      &lt;td&gt;否&lt;/td&gt;
      &lt;td&gt;大部分情况下，这个寄存器是当前窗口中，上一次访问的缓冲区。请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h alternate-file&lt;/code&gt; 来获取更多帮助&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Expression&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;用户&lt;/td&gt;
      &lt;td&gt;否&lt;/td&gt;
      &lt;td&gt;复制 VimL 代码时，这个寄存器用于存储代码片段的执行结果。比如，在插入模式下复制 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-r&amp;gt;=5+5&amp;lt;cr&amp;gt;&lt;/code&gt;，那么这个寄存器就会存入 10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Selection&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;vim&lt;/td&gt;
      &lt;td&gt;否&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; 是 &lt;a href=&quot;#剪贴板&quot;&gt;剪贴板&lt;/a&gt; 寄存器&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Drop&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;vim&lt;/td&gt;
      &lt;td&gt;是&lt;/td&gt;
      &lt;td&gt;最后一次拖拽添加至 Vim 的文本（需要 “+dnd” 支持，暂时只支持 GTK GUI。请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:help dnd&lt;/code&gt; 及 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:help quote~&lt;/code&gt;）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Black hole&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;vim&lt;/td&gt;
      &lt;td&gt;否&lt;/td&gt;
      &lt;td&gt;一般称为黑洞寄存器。对于当前操作，如果你不希望在其他寄存器中保留文本，那就在命令前加上 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt;。比如，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;_dd&lt;/code&gt; 命令不会将文本放到寄存器 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; 中&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Last search pattern&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;vim&lt;/td&gt;
      &lt;td&gt;否&lt;/td&gt;
      &lt;td&gt;最近一次通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:global&lt;/code&gt; 等命令调用的匹配条件&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

只要不是只读的寄存器，用户都有权限修改它的内容，比如：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; @/ &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;register&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这样，我们按 &lt;kbd&gt;n&lt;/kbd&gt; 的时候就会跳转到单词”register” 出现的地方。

有些时候，你的操作可能已经修改了寄存器，而你没有察觉到。请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h registers&lt;/code&gt; 获取更多帮助。

上面提到过，复制的命令是 &lt;kbd&gt;y&lt;/kbd&gt;，粘贴的命令是 &lt;kbd&gt;p&lt;/kbd&gt; 或者 &lt;kbd&gt;P&lt;/kbd&gt;。但请注意，Vim 会区分「字符选取」与「行选取」。请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h linewise&lt;/code&gt; 获取更多帮助。

&lt;strong&gt;行选取&lt;/strong&gt;：
命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yy&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Y&lt;/code&gt; 都是复制当前行。这时移动光标至其他位置，按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p&lt;/code&gt; 就可以在光标下方粘贴复制的行，按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;P&lt;/code&gt; 就可以在光标上方粘贴至复制的行。

&lt;strong&gt;字符选取&lt;/strong&gt;：
命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0yw&lt;/code&gt; 可以复制第一个单词。这时移动光标至其他位置，按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p&lt;/code&gt; 就可以在当前行、光标后的位置粘贴单词，按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;P&lt;/code&gt; 就可以在当前行、光标前的位置粘贴单词。

&lt;strong&gt;将文本存到指定的寄存器中&lt;/strong&gt;：
命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;aY&lt;/code&gt; 可以将当前行复制，并存储到寄存器 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; 中。这时移动光标至其他位置，通过命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;AY&lt;/code&gt; 就可以把这一行的内容扩展到寄存器 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; 中，而之前存储的内容也不会丢失。

为了便于理解和记忆，建议大家现在就试一试上面提到的这些操作。操作过程中，你可以随时通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:reg&lt;/code&gt; 来查看寄存器的变化。

&lt;strong&gt;有趣的是&lt;/strong&gt;：
在 Vim 中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; 是复制命令，源于单词 “yanking”。而在 Emacs 中，”yanking” 代表的是粘贴（或者说，重新插入刚才删掉的内容），而并不是复制。

&lt;h3 id=&quot;范围&quot;&gt;范围&lt;/h3&gt;

范围 (Ranges) 其实很好理解，但很多 Vim 用户的理解不到位。

&lt;ul&gt;
  &lt;li&gt;很多命令都可以加一个数字，用于指明操作范围&lt;/li&gt;
  &lt;li&gt;范围可以是一个行号，用于指定某一行&lt;/li&gt;
  &lt;li&gt;范围也可以是一对通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;,&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;;&lt;/code&gt; 分割的行号&lt;/li&gt;
  &lt;li&gt;大部分命令，默认只作用于当前行&lt;/li&gt;
  &lt;li&gt;只有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:write&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:global&lt;/code&gt; 是默认作用于所有行的&lt;/li&gt;
&lt;/ul&gt;

范围的使用是十分直观的。以下为一些例子（其中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:d&lt;/code&gt; 为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:delete&lt;/code&gt; 的缩写）：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;命令&lt;/th&gt;
      &lt;th&gt;操作的行&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:.d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:1d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;第一行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:$d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;最后一行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:1,$d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;所有行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:%d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;所有行（这是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1,$&lt;/code&gt; 的语法糖）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:.,5d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前行至第 5 行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:,5d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;同样是当前行至第 5 行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:,+3d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前行及接下来的 3 行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:1,+3d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;第一行至当前行再加 3 行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:,-3d&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前行及向上的 3 行（Vim 会弹出提示信息，因为这是一个保留的范围）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:3,&apos;xdelete&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;第三行至&lt;a href=&quot;#标注&quot;&gt;标注&lt;/a&gt; 为 x 的那一行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:/^foo/,$delete&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前行以下，以字符 “foo” 开头的那一行至结尾&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:/^foo/+1,$delete&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前行以下，以字符 “foo” 开头的那一行的下一行至结尾&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

需要注意的是，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;;&lt;/code&gt; 也可以用于表示范围。区别在于，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a,b&lt;/code&gt; 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; 是以当前行作为参考的。而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a;b&lt;/code&gt; 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; 是以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; 行作为参考的。举个例子，现在你的光标在第 5 行。这时 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:1,+1d&lt;/code&gt; 会删除第 1 行至第 6 行，而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:1;+1d&lt;/code&gt; 会删除第 1 行和第 2 行。

如果你想设置多个寻找条件，只需要在条件前加上 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;，比如：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/foo//bar//quux/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这就会删除当前行之后的某一行。定位方式是，先在当前行之后寻找第一个包含 “foo” 字符的那一行，然后在找到的这一行之后寻找第一个包含 “bar” 字符的那一行，然后再在找到的这一行之后寻找第一个包含 “quux” 的那一行。删除的就是最后找到的这一行。

有时，Vim 会在命令前自动添加范围。举个例子，如果你先通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;V&lt;/code&gt; 命令进入行选取模式，选中一些行后按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt; 进入命令模式，这时候你会发现 Vim 自动添加了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&amp;lt;,&apos;&amp;gt;&lt;/code&gt; 范围。这表示，接下来的命令会使用之前选取的行号作为范围。但如果后续命令不支持范围，Vim 就会报错。为了避免这样的情况发生，有些人会设置这样的按键映射：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:vnoremap foo :&amp;lt;c-u&amp;gt;command&lt;/code&gt;，组合键 &lt;kbd&gt;Ctrl + u&lt;/kbd&gt; 可以清除当前命令行中的内容。

另一个例子是在普通模式中按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!!&lt;/code&gt;，命令行中会出现 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:.!&lt;/code&gt;。如果这时你如果输入一个外部命令，那么当前行的内容就会被这个外部命令的输出替换。你也可以通过命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:?^$?+1,/^$/-1!ls&lt;/code&gt; 把当前段落的内容替换成外部命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls&lt;/code&gt; 的输出，原理是向前和向后各搜索一个空白行，删除这两个空白行之间的内容，并将外部命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls&lt;/code&gt; 的输出放到这两个空白行之间。

请参阅以下两个命令来获取更多帮助：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; cmdline&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;ranges
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;标注&quot;&gt;标注&lt;/h3&gt;

你可以使用标注功能来标记一个位置，也就是记录文件某行的某个位置。

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;标注&lt;/th&gt;
      &lt;th&gt;设置者&lt;/th&gt;
      &lt;th&gt;使用&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt;-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;z&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;用户&lt;/td&gt;
      &lt;td&gt;仅对当前的一个文件生效，也就意味着只可以在当前文件中跳转&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Z&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;用户&lt;/td&gt;
      &lt;td&gt;全局标注，可以作用于不同文件。大写标注也称为「文件标注」。跳转时有可能会切换到另一个缓冲区&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;viminfo&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; 代表 viminfo 最后一次被写入的位置。实际使用中，就代表 Vim 进程最后一次结束的位置。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; 代表 Vim 进程倒数第二次结束的位置，以此类推&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

如果想跳转到指定的标注，你可以先按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g&apos;&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g`&lt;/code&gt; 然后按下标注名。

如果你想定义当前文件中的标注，可以先按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m&lt;/code&gt; 再按下标注名。比如，按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mm&lt;/code&gt; 就可以把当前位置标注为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m&lt;/code&gt;。在这之后，如果你的光标切换到了文件的其他位置，只需要通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;m&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`m&lt;/code&gt;即可回到刚才标注的行。区别在于，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;m&lt;/code&gt;会跳转回被标记行的第一个非空字符，而&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`m&lt;/code&gt;会跳转回被标记行的被标记列。根据 viminfo 的设置，你可以在退出 Vim 的时候保留小写字符标注。请参阅&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h viminfo-&apos;&lt;/code&gt; 来获取更多帮助。

如果你想定义全局的标注，可以先按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m&lt;/code&gt; 再按下大写英文字符。比如，按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mM&lt;/code&gt; 就可以把当前文件的当前位置标注为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M&lt;/code&gt;。在这之后，就算你切换到其他的缓冲区，依然可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;M&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`M&lt;/code&gt; 跳转回来。

关于跳转，还有以下的方式：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;按键&lt;/th&gt;
      &lt;th&gt;跳转至&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;[&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`[&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;上一次修改或复制的第一行或第一个字符&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;]&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;上一次修改或复制的最后一行或最后一个字符&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&amp;lt;&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`&amp;lt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;上一次在可视模式下选取的第一行或第一个字符&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&amp;gt;&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;上一次在可视模式下选取的最后一行或最后一个字符&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&apos;&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`&apos;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;上一次跳转之前的光标位置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&quot;&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`&quot;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;上一次关闭当前缓冲区时的光标位置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;^&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`^&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;上一次插入字符后的光标位置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;.&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`.&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;上一次修改文本后的光标位置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;(&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`(&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前句子的开头&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;)&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前句子的结尾&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;{&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`{&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前段落的开头&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;}&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前段落的结尾&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

标注也可以搭配 &lt;a href=&quot;#范围&quot;&gt;范围&lt;/a&gt; 一起使用。前面提到过，如果你在可视模式下选取一些文本，然后按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt;，这时候你会发现命令行已经被填充了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&apos;&amp;lt;,&apos;&amp;gt;&lt;/code&gt;。对照上面的表格，现在你应该明白了，这段代表的就是可视模式下选取的范围。

请使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:marks&lt;/code&gt; 命令来显示所有的标注，参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h mark-motions&lt;/code&gt; 来获取关于标注的更多帮助。

&lt;h3 id=&quot;补全&quot;&gt;补全&lt;/h3&gt;

Vim 在插入模式中为我们提供了多种补全方案。如果有多个补全结果，Vim 会弹出一个菜单供你选择。

常见的补全有标签、项目中引入的模块或库中的方法名、文件名、字典及当前缓冲区的字段。

针对不同的补全方案，Vim 为我们提供了不同的按键映射。这些映射都是在&lt;strong&gt;插入模式中&lt;/strong&gt;通过 &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;x&lt;/kbd&gt; 来触发：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;映射&lt;/th&gt;
      &lt;th&gt;类型&lt;/th&gt;
      &lt;th&gt;帮助文档&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-x&amp;gt;&amp;lt;c-l&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;整行&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i^x^l&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-x&amp;gt;&amp;lt;c-n&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前缓冲区中的关键字&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i^x^n&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-x&amp;gt;&amp;lt;c-k&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;字典（请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;dictionary&apos;&lt;/code&gt;）中的关键字&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i^x^k&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-x&amp;gt;&amp;lt;c-t&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;同义词字典（请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;thesaurus&apos;&lt;/code&gt;）中的关键字&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i^x^t&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-x&amp;gt;&amp;lt;c-i&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;当前文件以及包含的文件中的关键字&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i^x^i&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-x&amp;gt;&amp;lt;c-]&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;标签&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i^x^]&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-x&amp;gt;&amp;lt;c-f&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;文件名&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i^x^f&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-x&amp;gt;&amp;lt;c-d&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;定义或宏定义&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i^x^d&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-x&amp;gt;&amp;lt;c-v&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Vim 命令&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i^x^v&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-x&amp;gt;&amp;lt;c-u&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;用户自定义补全（通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;completefunc&apos;&lt;/code&gt; 定义）&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i^x^u&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-x&amp;gt;&amp;lt;c-o&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Omni Completion（通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;omnifunc&apos;&lt;/code&gt; 定义）&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i^x^o&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-x&amp;gt;s&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;拼写建议&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i^Xs&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

尽管用户自定义补全与 Omni Completion 是不同的，但他们做的事情基本一致。共同点在于，他们都是一个监听当前光标位置的函数，返回值为一系列的补全建议。用户自定义补全是由用户定义的，基于用户的个人用途，因此你可以根据自己的喜好和需求随意定制。而 Omni Completion 是针对文件类型的补全，比如在 C 语言中补全一个结构体（struct）的成员（members），或者补全一个类的方法，因而它通常都是由文件类型插件设置和调用的。

如果你设置了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;complete&apos;&lt;/code&gt; 选项，那么你就可以在一次操作中采用多种补全方案。这个选项默认包含了多种可能性，因此请按照自己的需求来配置。你可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-n&amp;gt;&lt;/code&gt; 来调用下一个补全建议，或通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-p&amp;gt;&lt;/code&gt; 来调用上一个补全建议。当然，这两个映射同样可以直接调用补全函数。请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i^n&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;complete&apos;&lt;/code&gt; 来获得更多帮助。

如果你想配置弹出菜单的行为，请一定要看一看 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;completeopt&apos;&lt;/code&gt; 这篇帮助文档。默认的配置已经不错了，但我个人（原作者）更倾向于把 “noselect” 加上。

请参阅以下文档获取更多帮助：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; ins&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;completion
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; popupmenu&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;keys&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;omni&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;completion
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;动作操作符文本对象&quot;&gt;动作，操作符，文本对象&lt;/h3&gt;

&lt;strong&gt;动作&lt;/strong&gt;也就是指移动光标的操作，你肯定很熟悉 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;l&lt;/code&gt;，以及 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;。但其实，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; 也是一个动作。他们都可以搭配数字使用，比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2?the&amp;lt;cr&amp;gt;&lt;/code&gt; 可以将光标移动到倒数第二个 “the” 出现的位置。

以下会列出一些常用的动作。你也可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h navigation&lt;/code&gt; 来获取更多的帮助。

&lt;strong&gt;操作符&lt;/strong&gt;是对某个区域文本执行的操作。比如，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gU&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; 都是操作符。这些操作符既可以在普通模式下使用，也可以在可视模式下使用。在普通模式中，顺序是先按操作符，再按动作指令，比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;j&lt;/code&gt;。在可视模式中，选中区域后直接按操作符就可以，比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Vjd&lt;/code&gt;。

与动作一样，操作符也可以搭配数字使用，比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2gUw&lt;/code&gt; 可以将当前单词以及下一个单词转成大写。由于动作和操作符都可以搭配数字使用，因此 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2gU2w&lt;/code&gt; 与执行两次 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gU2w&lt;/code&gt; 效果是相同的。

请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h operator&lt;/code&gt; 来查看所有的操作符。你也可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set tildeop&lt;/code&gt; 命令把 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; 也变成一个操作符

值得注意的是，动作是单向的，而&lt;strong&gt;文本对象&lt;/strong&gt;是双向的。文本对象不仅作用于符号（比如括号、中括号和大括号等）标记的范围内，也作用于整个单词、整个句子等其他情况。

文本对象不能用于普通模式中移动光标的操作，因为光标还没有智能到可以向两个方向同时跳转。但这个功能可以在可视模式中实现，因为在对象的一端选中的情况下，光标只需要跳转到另一端就可以了。

文本对象操作一般用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; 加上对象标识符操作，其中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; 表示在对象内（英文 inner）操作，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; 表示对整个对象（英文 around）操作，这时开头和结尾的空格都会被考虑进来。举个例子，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diw&lt;/code&gt; 可以删除当前单词，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ci(&lt;/code&gt; 可以改变括号中的内容。

文本对象同样可以与数字搭配使用。比如，像 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;((( )))&lt;/code&gt; 这样的文本，假如光标位于最内层的括号上或最内层的括号内，那么 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d2a(&lt;/code&gt; 将会删除从最内层开始的两对括号，以及他们之间的所有内容。其实，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d2a(&lt;/code&gt; 这个操作等同于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2da(&lt;/code&gt;。在 Vim 的命令中，如果有两处都可以接收数字作为参数，那么最终结果就等同于两个数字相乘。在这里，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a(&lt;/code&gt; 都是可以接收参数的，一个参数是 1，另一个是 2，我们可以把它们相乘然后放到最前面。

请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h text-objects&lt;/code&gt; 来获取更多关于文本对象的帮助。

&lt;h3 id=&quot;自动命令&quot;&gt;自动命令&lt;/h3&gt;

在特定的情况下，Vim 会传出事件。如果你想针对这些事件执行回调方法，那么就需要用到自动命令这个功能。

如果没有了自动命令，那你基本上是用不了 Vim 的。自动命令一直都在执行，只是很多时候你没有注意到。不信的话，可以执行命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:au&lt;/code&gt; ，不要被结果吓到，这些是当前有效的所有自动命令。

请使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h {event}&lt;/code&gt; 来查看 Vim 中所有事件的列表，你也可以参考 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h autocmd-events-abc&lt;/code&gt; 来获取关于事件的更多帮助。

一个很常用的例子，就是针对文件类型执行某些设置：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;FileType&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ruby&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;setlocal&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;shiftwidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;softtabstop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;comments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-=:&lt;/span&gt;#
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

但是缓冲区是如何知道当前的文件中包含 Ruby 代码呢？这其实是另一个自动命令检测的到的，然后把文件类型设置成为 Ruby，这样就触发了上面的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FileType&lt;/code&gt; 事件。

在配置 vimrc 的时候，一般第一行加进去的就是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filetype on&lt;/code&gt;。这就意味着，Vim 启动时会读取 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filetype.vim&lt;/code&gt; 文件，然后根据文件类型来触发相应的自动命令。

如果你勇于尝试，可以查看下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:e $VIMRUNTIME/filetype.vim&lt;/code&gt;，然后在输出中搜索 “Ruby”。这样，你就会发现其实 Vim 只是通过文件扩展名 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rb&lt;/code&gt; 判断某个文件是不是 Ruby 的。

&lt;strong&gt;注意&lt;/strong&gt;：对于相同事件，如果有多个自动命令，那么自动命令会按照定义时的顺序执行。通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:au&lt;/code&gt; 就可以查看它们的执行顺序。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;au&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;BufNewFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;BufRead&lt;/span&gt; *&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;rb&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;*&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;rbw &lt;span class=&quot;k&quot;&gt;setf&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ruby&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BufNewFile&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BufRead&lt;/code&gt; 事件是被写在 Vim 源文件中的。因此，每当你通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:e&lt;/code&gt; 或者类似的命令打开文件，这两个事件都会触发。然后，就是读取 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filetype.vim&lt;/code&gt; 文件来判断打开的文件类型。

简单来说，事件和自动命令在 Vim 中的应用十分广泛。而且，Vim 为我们留出了一些易用的接口，方便用户配置适合自己的事件驱动回调。

请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h autocommand&lt;/code&gt; 来获取更多帮助

&lt;h3 id=&quot;变更历史跳转历史&quot;&gt;变更历史，跳转历史&lt;/h3&gt;

在 Vim 中，用户最近 100 次的文字改动都会被保存在&lt;strong&gt;变更历史&lt;/strong&gt;中。如果在同一行有多个小改动，那么 Vim 会把它们合并成一个。尽管内容改动会合并，但作用的位置还是会只记录下最后一次改动的位置。

在你移动光标或跳转的时候，每一次的移动或跳转前的位置会被记录到&lt;strong&gt;跳转历史&lt;/strong&gt;中。类似地，跳转历史也可以最多保存 100 条记录。对于每个窗口，跳转记录是独立的。但当你分离窗口时（比如使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:split&lt;/code&gt; 命令），跳转历史会被复制过去。

Vim 中的跳转命令，包括 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[[&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;]]&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;}&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:s&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:tag&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;H&lt;/code&gt; 以及开始编辑一个新文件的命令。

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;列表&lt;/th&gt;
      &lt;th&gt;显示所有条目&lt;/th&gt;
      &lt;th&gt;跳转到上一个位置&lt;/th&gt;
      &lt;th&gt;跳转到下一个位置&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;跳转历史&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:jumps&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[count]&amp;lt;c-o&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[count]&amp;lt;c-i&amp;gt;&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;变更历史&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:changes&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[count]g;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[count]g,&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

如果你执行第二列的命令显示所有条目，这时 Vim 会用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; 标记来为你指示当前位置。通常这个标记位于 1 的下方，也就代表最后一次的位置。

如果你希望关闭 Vim 之后还保留这些条目，请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h viminfo-&apos;&lt;/code&gt; 来获取更多帮助。

&lt;strong&gt;注意&lt;/strong&gt;：上面提到过，最后一次跳转前的位置也会记录在&lt;a href=&quot;#标注&quot;&gt;标注&lt;/a&gt;中，也可以通过连按 &lt;kbd&gt;\`\`&lt;/kbd&gt; 或 &lt;kbd&gt;&apos;&apos;&lt;/kbd&gt; 跳转到那个位置

请参阅以下两个命令来获取更多帮助：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; changelist
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; jumplist
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;内容变更历史记录&quot;&gt;内容变更历史记录&lt;/h3&gt;

Vim 会记录文本改变之前的状态。因此，你可以使用「撤销」操作 &lt;kbd&gt;u&lt;/kbd&gt; 来取消更改，也可以通过「重做」操作 &lt;kbd&gt;Ctrl + r&lt;/kbd&gt; 来恢复更改。

值得注意的是，Vim 采用 &lt;a href=&quot;https://en.wikipedia.org/wiki/Tree_(data_structure)&quot;&gt;tree&lt;/a&gt; 数据结构来存储内容变更的历史记录，而不是采用 &lt;a href=&quot;https://en.wikipedia.org/wiki/Queue_(abstract_data_type)&quot;&gt;queue&lt;/a&gt;。你的每次改动都会成为存储为树的节点。而且，除了第一次改动（根节点），之后的每次改动都可以找到一个对应的父节点。每一个节点都会记录改动的内容和时间。其中，「分支」代表从任一节点到根节点的路径。当你进行了撤销操作，然后又输入了新的内容，这时候就相当于创建了分支。这个原理和 git 中的 branch（分支）十分类似。

考虑以下这一系列按键操作：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ifoo&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;esc&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
obar&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;esc&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
obaz&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;esc&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;u&lt;/span&gt;
oquux&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;exc&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

那么现在，Vim 中会显示三行文本，分别是 “foo”、”bar” 和 “quux”。这时候，存储的树形结构如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     foo(1)
       /
    bar(2)
   /      \
baz(3)   quux(4)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这个树形结构共包含四次改动，括号中的数字就代表时间顺序。

现在，我们有两种方式遍历这个树结构。一种叫「按分支遍历」，一种叫「按时间遍历」。

撤销 &lt;kbd&gt;u&lt;/kbd&gt; 与重做 &lt;kbd&gt;Ctrl + r&lt;/kbd&gt; 操作是按分支遍历。对于上面的例子，现在我们有三行字符。这时候按 &lt;kbd&gt;u&lt;/kbd&gt; 会回退到 “bar” 节点，如果再按一次 &lt;kbd&gt;u&lt;/kbd&gt; 则会回退到 “foo” 节点。这时，如果我们按下 &lt;kbd&gt;Ctrl + r&lt;/kbd&gt; 就会前进至 “bar” 节点，再按一次就回前进至 “quux” 节点。在这种方式下，我们无法访问到兄弟节点（即 “baz” 节点）。

与之对应的是按时间遍历，对应的按键是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g-&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g+&lt;/code&gt;。对于上面的例子，按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g-&lt;/code&gt; 会首先回退到 “baz” 节点。再次按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g-&lt;/code&gt; 会回退到 “bar” 节点。

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;命令/按键&lt;/th&gt;
      &lt;th&gt;执行效果&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[count]u&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:undo [count]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;回退到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[count]&lt;/code&gt; 次改动之前&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[count]&amp;lt;c-r&amp;gt;&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:redo [count]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;重做 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[count]&lt;/code&gt; 次改动&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;U&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;回退至最新的改动&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[count]g-&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:earlier [count]?&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;根据时间回退到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[count]&lt;/code&gt; 次改动之前。”?” 为 “s”、”m”、”h”、”d” 或 “f”之一。例如，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:earlier 2d&lt;/code&gt; 会回退到两天之前。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:earlier 1f&lt;/code&gt; 则会回退到最近一次文件保存时的内容&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[count]g+&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:later [count]?&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;类似 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g-&lt;/code&gt;，但方向相反&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

内容变更记录会储存在内存中，当 Vim 退出时就会清空。如果需要持久化存储内容变更记录，请参阅&lt;a href=&quot;#备份文件交换文件撤销文件以及viminfo文件的处理&quot;&gt;备份文件，交换文件，撤销文件以及 viminfo 文件的处理&lt;/a&gt;章节的内容。

如果你觉得这一部分的内容难以理解，请参阅 &lt;a href=&quot;https://github.com/mbbill/undotree&quot;&gt;undotree&lt;/a&gt;，这是一个可视化管理内容变更历史记录的插件。类似的还有 &lt;a href=&quot;https://github.com/simnalamburt/vim-mundo&quot;&gt;vim-mundo&lt;/a&gt;。

请参阅以下链接获取更多帮助：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;undo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;txt
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; usr_32
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;全局位置信息表局部位置信息表&quot;&gt;全局位置信息表，局部位置信息表&lt;/h3&gt;

在某一个动作返回一系列「位置」的时候，我们可以利用「全局位置信息表」和「局部位置信息表」来存储这些位置信息，方便以后跳转回对应的位置。每一个存储的位置包括文件名、行号和列号。

比如，编译代码是出现错误，这时候我们就可以把错误的位置直接显示在全局位置信息表，或者通过外部抓取工具使位置显示在局部位置信息表中。

尽管我们也可以把这些信息显示到一个空格缓冲区中，但用这两个信息表显示的好处在于接口调用很方便，而且也便于浏览输出。

Vim 中，全局位置信息表只能有一个，但每一个窗口都可以有自己的局部位置信息表。这两个信息表的外观看上去很类似，但在操作上会稍有不同。

以下为两者的操作比较：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;动作&lt;/th&gt;
      &lt;th&gt;全局位置信息表&lt;/th&gt;
      &lt;th&gt;局部位置信息表&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;打开窗口&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:copen&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:lopen&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;关闭窗口&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:cclose&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:lclose&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;下一个条目&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:cnext&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:lnext&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;上一个条目&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:cprevious&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:lprevious&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第一个条目&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:cfirst&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:lfirst&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;最后一个条目&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:clast&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:llast&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :cc&lt;/code&gt; 以及底下的内容，来获取更多命令的帮助。

&lt;strong&gt;应用实例&lt;/strong&gt;：
如果我们想用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; 递归地在当前文件夹中寻找某个关键词，然后把输出结果放到全局位置信息表中，只需要这样：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;grepprg&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;grep -Rn $* .&apos;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;grep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; foo
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;grep&lt;/span&gt; output &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; hit enter&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;copen&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行了上面的代码，你就能看到所有包含字符串 “foo” 的文件名以及匹配到的相关字段都会显示在全局位置信息表中。

&lt;h3 id=&quot;宏&quot;&gt;宏&lt;/h3&gt;

你可以在 Vim 中录制一系列按键，并把他们存储到&lt;a href=&quot;#寄存器&quot;&gt;寄存器&lt;/a&gt;中。对于一些需要临时使用多次的一系列操作，把它们作为宏保存起来会显著地提升效率。对于一些复杂的操作，建议使用 Vim 脚本来实现。

&lt;ul&gt;
  &lt;li&gt;首先，按下 &lt;kbd&gt;q&lt;/kbd&gt;，然后按下你想要保存的寄存器，任何小写字母都可以。比如我们来把它保存到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;q&lt;/code&gt; 这个寄存器中。按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qq&lt;/code&gt;，你会发现命令行里已经显示了 “recording @q”。&lt;/li&gt;
  &lt;li&gt;如果你已经录制完成，那么只需要再按一次 &lt;kbd&gt;q&lt;/kbd&gt; 就可以结束录制。&lt;/li&gt;
  &lt;li&gt;如果你想调用刚才录制的宏，只需要 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[count]@q&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;如果你想调用上一次使用的宏，只需要 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[count]@@&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;strong&gt;实例 1&lt;/strong&gt;：

一个插入字符串 “abc” 后换行的宏，重复调用十次：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;qq
&lt;span class=&quot;k&quot;&gt;iabc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;esc&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;q&lt;/span&gt;
&lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;@&lt;span class=&quot;k&quot;&gt;q&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

（对于上面这个功能，你同样可以通过如下的按键： &lt;kbd&gt;o&lt;/kbd&gt;&lt;kbd&gt;a&lt;/kbd&gt;&lt;kbd&gt;b&lt;/kbd&gt;&lt;kbd&gt;c&lt;/kbd&gt; 然后 &lt;kbd&gt;ESC&lt;/kbd&gt; 然后 &lt;kbd&gt;1&lt;/kbd&gt;&lt;kbd&gt;0&lt;/kbd&gt;&lt;kbd&gt;.&lt;/kbd&gt; 来实现）。

&lt;strong&gt;实例 2&lt;/strong&gt;：

一个在每行前都加上行号的宏。从第一行开始，行号为 1，后面依次递增。我们可以通过 &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;a&lt;/kbd&gt; 来实现递增的行号，在定义宏的时候，它会显示成 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^A&lt;/code&gt;。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;qq
&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;yf jP0^A
&lt;span class=&quot;k&quot;&gt;q&lt;/span&gt;
&lt;span class=&quot;m&quot;&gt;1000&lt;/span&gt; @&lt;span class=&quot;k&quot;&gt;q&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这里能实现功能，是因为我们假定了文件最多只有 1000 行。但更好的方式是使用「递归」宏，它会一直执行，知道不能执行为止：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;qq
&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;yf jP0^A@&lt;span class=&quot;k&quot;&gt;q&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;q&lt;/span&gt;
@&lt;span class=&quot;k&quot;&gt;q&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

（对于上面这个插入行号的功能，如果你不愿意使用宏，同样可以通过这段按键操作来实现：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:%s/^/\=line(&apos;.&apos;) . &apos;. &apos;&lt;/code&gt;）。

这里向大家展示了如何不用宏来达到相应的效果，但要注意，这些不用宏的实现方式只适用于这些简单的示例。对于一些比较复杂的自动化操作，你确实应该考虑使用宏。

请参阅以下文档获取更多帮助：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; recording
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;lazyredraw&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;颜色主题&quot;&gt;颜色主题&lt;/h3&gt;

颜色主题可以把你的 Vim 变得更漂亮。Vim 是由多个组件构成的，我们可以给每一个组件都设置不同的文字颜色、背景颜色以及文字加粗等等。比如，我们可以通过这个命令来设置背景颜色：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;highlight&lt;/span&gt; Normal ctermbg&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; guibg&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;red&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行后你会发现，现在背景颜色变成红色了。请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :highlight&lt;/code&gt; 来获取更多帮助。

其实，颜色主题就是一系列的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:highlight&lt;/code&gt; 命令的集合。

事实上，大部分颜色主题都包含两套配置。一套适用于例如 xterm 和 iTerm 这样的终端环境（使用前缀 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cterm&lt;/code&gt;），另一套适用于例如 gvim 和 MacVim 的图形界面环境（使用前缀 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gui&lt;/code&gt;）。对于上面的例子，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctermbg&lt;/code&gt; 就是针对终端环境的，而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;guibg&lt;/code&gt; 就是针对图形界面环境的。

如果你下载了一个颜色主题，并且在终端环境中打开了 Vim，然后发现显示的颜色与主题截图中差别很大，那很可能是配置文件只设置了图形界面环境的颜色。反之同理，如果你使用的是图形界面环境，发现显示颜色有问题，那就很可能是配置文件只设置了终端环境的颜色。

第二种情况（图形界面环境的显示问题）其实不难解决。如果你使用的是 Neovim 或者 Vim 7.4.1830 的后续版本，可以通过打开&lt;a href=&quot;https://zh.wikipedia.org/wiki/真彩色&quot;&gt;真彩色&lt;/a&gt;设置来解决显示问题。这就可以让终端环境的 Vim 使用 GUI 的颜色定义，但首先，你要确认一下你的终端环境和环境内的组件（比如 tmux）是否都支持真彩色。可以看一下&lt;a href=&quot;https://gist.github.com/XVilka/8346728&quot;&gt;这篇文档&lt;/a&gt;，描述的十分详细。

请参阅以下文档或链接来获取更多帮助：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;termguicolors&apos;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#主题列表&quot;&gt;主题列表&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#自定义主题中的颜色&quot;&gt;自定义主题中的颜色&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;折叠&quot;&gt;折叠&lt;/h3&gt;

每一部分文字（或者代码）都会有特定的结构。对于存在结构的文字和代码，也就意味着它们可以按照一定的逻辑分割成不同区域。Vim 中的折叠功能，就是按照特定的逻辑把文字和代码折叠成一行，并显示一些简短的描述。折叠功能涉及到很多操作，而且折叠功能可以嵌套使用。

在 Vim 中，有以下 6 中折叠类型：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;折叠方式&lt;/th&gt;
      &lt;th&gt;概述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;diff&lt;/td&gt;
      &lt;td&gt;在「比较窗口」中折叠未改变的文本&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;expr&lt;/td&gt;
      &lt;td&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;foldexpr&apos;&lt;/code&gt; 来创建新的折叠逻辑&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;indent&lt;/td&gt;
      &lt;td&gt;基于缩进折叠&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;manual&lt;/td&gt;
      &lt;td&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zf&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zF&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:fold&lt;/code&gt; 来自定义折叠&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;marker&lt;/td&gt;
      &lt;td&gt;根据特定的文本标记折叠（通常用于代码注释）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;syntax&lt;/td&gt;
      &lt;td&gt;根据语法折叠，比如折叠 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; 代码块&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;strong&gt;注意&lt;/strong&gt;：折叠功能可能会显著地影响性能。如果你在使用折叠功能的时候出现了打字卡顿之类的问题，请考虑使用 &lt;a href=&quot;https://github.com/Konfekt/FastFold&quot;&gt;FastFold 插件&lt;/a&gt;。这个插件可以让 Vim 按需更新折叠内容，而不是一直调用。

请参阅以下文档获取更多帮助：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; usr_28
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; folds
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;会话&quot;&gt;会话&lt;/h3&gt;

如果你保存了当前的「视图」（请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :mkview&lt;/code&gt;），那么当前窗口、配置和按键映射都会被保存下来（请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :loadview&lt;/code&gt;）。

「会话」就是存储所有窗口的相关设置，以及全局设置。简单来说，就是给当前的 Vim 运行实例拍个照，然后把相关信息存储到会话文件中。存储之后的改动就不会在会话文件中显示，你只需要在改动后更新一下会话文件就可以了。

你可以把当前工作的「项目」存储起来，然后可以在不同的「项目」之间切换。

现在就来试试吧。打开几个窗口和标签，然后执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:mksession Foo.vim&lt;/code&gt;。如果你没有指定文件名，那就会默认保存为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Session.vim&lt;/code&gt;。这个文件会保存在当前的目录下，你可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:pwd&lt;/code&gt; 来显示当前路径。重启 Vim 之后，你只需要执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:source Foo.vim&lt;/code&gt;，就可以恢复刚才的会话了。所有的缓冲区、窗口布局、按键映射以及工作路径都会恢复到保存时的状态。

其实 Vim 的会话文件就只是 Vim 命令的集合。你可以通过命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:vs Foo.vim&lt;/code&gt; 来看看会话文件中究竟有什么。

你可以决定 Vim 会话中究竟要保存哪些配置，只需要设置一下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;sessionoptions&apos;&lt;/code&gt; 就可以了。

为了方便开发，Vim 把最后一次调用或写入的会话赋值给了一个内部变量 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v:this_session&lt;/code&gt;。

请参阅以下文档来获取更多帮助：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; Session
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;sessionoptions&apos;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;this_session
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;局部化&quot;&gt;局部化&lt;/h3&gt;

以上提到的很多概念，都有一个局部化（非全局）的版本：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;全局&lt;/th&gt;
      &lt;th&gt;局部&lt;/th&gt;
      &lt;th&gt;作用域&lt;/th&gt;
      &lt;th&gt;帮助文档&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:setlocal&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;缓冲区或窗口&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h local-options&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:map&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:map &amp;lt;buffer&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;缓冲区&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :map-local&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:autocmd&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:autocmd * &amp;lt;buffer&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;缓冲区&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h autocmd-buflocal&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:cd&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:lcd&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;窗口&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :lcd&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&amp;lt;leader&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&amp;lt;localleader&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;缓冲区&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h maploacalleader&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

变量也有不同的作用域，详细内容请参考 &lt;a href=&quot;http://vimdoc.sourceforge.net/htmldoc/usr_41.html&quot;&gt;Vim scripting 的文档&lt;/a&gt;。

&lt;h2 id=&quot;用法&quot;&gt;用法&lt;/h2&gt;

&lt;h3 id=&quot;获取离线帮助&quot;&gt;获取离线帮助&lt;/h3&gt;

Vim 自带了一套很完善的帮助文档，它们是一个个有固定排版格式的文本文件，通过标签可以访问这些文件的特定位置。

在开始之前先读一下这个章节：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:help :help&lt;/code&gt;。执行这个命令以后会在新窗口打开 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$VIMRUNTIME/doc/helphelp.txt&lt;/code&gt; 文件并跳转到这个文件中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:help&lt;/code&gt; 标签的位置。

一些关于帮助主题的简单规则：

&lt;ul&gt;
  &lt;li&gt;用单引号把文本包起来表示选项，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;textwidth&apos;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;以小括号结尾表示 VimL 函数，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h reverse()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;以英文冒号开头表示命令，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :echo&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

使用快捷键 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-d&amp;gt;&lt;/code&gt; （这是 &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;d&lt;/kbd&gt;）来列出所有包含你当前输入的内容的帮助主题。如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h tab&amp;lt;c-d&amp;gt;&lt;/code&gt; 会列出所有包含 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tab&lt;/code&gt; 主题，从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;softtabstop&lt;/code&gt; 到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setting-guitablabel&lt;/code&gt; （译者注：根据安装的插件不同列出的选项也会不同）。

你想查看所有的 VimL 方法吗？很简单，只要输入：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h ()&amp;lt;c-d&amp;gt;&lt;/code&gt; 就可以了。你想查看所有与窗口相关的函数吗？输入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h win*()&amp;lt;c-d&amp;gt;&lt;/code&gt;。

相信你很快就能掌握这些技巧，但是在刚开始的时候，你可能对于该通过什么进行查找一点线索都没有。这时你可以想象一些与要查找的内容相关的关键字，再让 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:helpgrep&lt;/code&gt; 来帮忙。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;helpgrep&lt;/span&gt; backwards
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上面的命令会在所有的帮助文件中搜索“backwards”，然后跳转到第一个匹配的位置。所有的匹配位置都会被添加到全局位置信息表，用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:cp / :cn&lt;/code&gt; 可以在匹配位置之间进行切换。或者用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:copen&lt;/code&gt; 命令来打开全局位置信息表，将光标定位到你想要的位置，再按 回车就可以跳转到该匹配项。详细说明请参考 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h quickfix&lt;/code&gt;。

&lt;h3 id=&quot;获取离线帮助补充&quot;&gt;获取离线帮助（补充）&lt;/h3&gt;

这个列表最初发表在 &lt;a href=&quot;https://groups.google.com/forum/#!forum/vim_dev&quot;&gt;vim_dev&lt;/a&gt;，由 @chrisbra 编辑的，他是 Vim 开发人员中最活跃的一个。

经过一些微小的改动后，重新发布到了这里。

&lt;hr /&gt;

如果你知道你想要找什么，使用帮助系统的搜索会更简单一些，因为搜索出的主题都带有固定的格式。

而且帮助系统中的主题包含了你当前使用的 Vim 版本的所特有特性，而网上那些已经过时或者是早期发布的话题是不会包含这些的。

因此学习使用帮助系统以及它所用的语言是很有必要的。这里是一些例子（不一定全，我有可能忘了一些什么）。

（译者注：下面列表中提及的都是如何指定搜索主题以便快速准确的找到你想要的帮助）

&lt;ol&gt;
  &lt;li&gt;
    选项要用单引号引起来。用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;list&apos;&lt;/code&gt; 来查看列表选项帮助。只有你明确的知道你要找这么一个选项的时候才可以这么做，不然的话你可以用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h options.txt&lt;/code&gt; 来打开所有选项的帮助页面，再用正则表达式进行搜索，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/width&lt;/code&gt;。某些选项有它们自己的命名空间，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h cpo-a&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h cpo-A&lt;/code&gt;， &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h cpo-b&lt;/code&gt; 等等。
  &lt;/li&gt;
  &lt;li&gt;
    普通模式的命令不能用冒号作为前缀。使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h gt&lt;/code&gt; 来转到“gt”命令的帮助页面。
  &lt;/li&gt;
  &lt;li&gt;
    正则表达式以“/”开头，所以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h /\+&lt;/code&gt; 会带你到正则表达式中量词“+”的帮助页面。
  &lt;/li&gt;
  &lt;li&gt;
    组合键经常以一个字母开头表示它们可以在哪些模式中使用。如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h i_CTRL-X&lt;/code&gt; 会带你到插入模式下的 CTRL-X 命令的用法帮助页面，这是一个自动完成类的组合键。需要注意的是某些键是有固定写法的，如 Control 键写成 CTRL。还有，查找普通模式下的组合键帮助时，可以省略开头的字母“n”，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h CTRL-A&lt;/code&gt;。而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h c_CTRL-A&lt;/code&gt;（译者注：原文为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h c_CRTL-R&lt;/code&gt;，感觉改为 A 更符合上下文语境）会解释 CTRL-A 在命令模式下输入命令时的作用；&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h v_CTRL-A&lt;/code&gt; 说的是在可见模式下把光标所在处的数字加 1；&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h g_CTRL-A&lt;/code&gt; 则说的是 g 命令（你需要先按 “g” 的命令）。这里的 “g” 代表一个普通的命令，这个命令总是与其它的按键组合使用才生效，与 “z” 开始的命令相似。
  &lt;/li&gt;
  &lt;li&gt;
    寄存器是以 “quote” 开头的。如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h quote:&lt;/code&gt; （译者注：原文为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h quote&lt;/code&gt;，感觉作者想以”:”来举例）来查看关于”:”寄存器的说明。
  &lt;/li&gt;
  &lt;li&gt;
    关于 Vim 脚本（VimL）的帮助都在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h eval.txt&lt;/code&gt; 里。而某些方面的语言可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h expr-X&lt;/code&gt; 获取帮助，其中的 ‘X’ 是一个特定的字符，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h expr-!&lt;/code&gt; 会跳转到描述 VimL 中’!’（非）的章节。另外一个重要提示，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h function-list&lt;/code&gt; 来查看所有函数的简要描述，列表中包括函数名和一句话描述。
  &lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;关于映射都可以在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h map.txt&lt;/code&gt; 中找到。通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h mapmode-i&lt;/code&gt; 来查找 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:imap&lt;/code&gt; 命令的相关信息；通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h map-topic&lt;/code&gt; 来查找专门针对映射的帮助（译者注：topic 为一个占位符，正如上面的字符 ‘X’ 一样，在实际使用中需要替换成相应的单词）（如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :map-local&lt;/code&gt; 查询本地 buffer 的映射，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h map-bar&lt;/code&gt; 查询如何在映射中处理’&lt;/td&gt;
          &lt;td&gt;’)。&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    命令定义用 “command-“ 开头，如用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h command-bar&lt;/code&gt; 来查看自定义命令中’!’的作用。
  &lt;/li&gt;
  &lt;li&gt;
    窗口管理类的命令是以 “CTRL-W” 开头的，所以你可以用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h CTRL-W_*&lt;/code&gt; 来查找相应的帮助（译者注：’*‘同样为占位符）（如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h CTRL-W_p&lt;/code&gt; 查看切换到之前访问的窗口命令的解释）。如果你想找窗口处理的命令，还可以通过访问 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h windows.txt&lt;/code&gt; 并逐行向下浏览，所有窗口管理的命令都在这里了。
  &lt;/li&gt;
  &lt;li&gt;
    执行类的命令以”:”开头，即：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :s&lt;/code&gt; 讲的是 “:s” 命令。
  &lt;/li&gt;
  &lt;li&gt;
    在输入某个话题时按 CTRL-D，让 Vim 列出所有的近似项辅助你输入。
  &lt;/li&gt;
  &lt;li&gt;
    用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:helpgrep&lt;/code&gt; 在所有的帮助页面（通常还包括了已安装的插件的帮助页面）中进行搜索。参考 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :helpgrep&lt;/code&gt; 来了解如何使用。当你搜索了一个话题之后，所有的匹配结果都被保存到了全局位置信息表（或局部位置信息表）当中，可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:copen&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:lopen&lt;/code&gt; 打开。在打开的窗口中可能通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; 对搜索结果进行进一步的过滤。
  &lt;/li&gt;
  &lt;li&gt;
    &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h helphelp&lt;/code&gt; 里介绍了如何使用帮助系统。
  &lt;/li&gt;
  &lt;li&gt;
    用户手册。它采用了一种对初学者更加友好的方式来展示帮助话题。用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h usr_toc.txt&lt;/code&gt; 打开目录（你可能已经猜到这个命令的用处了）。浏览用户手册能帮助你找出某些你想了解的话题，如你可以在第 24 章看到关于“复合字符”以及“输入特殊字符”的讲解（用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h usr_24.txt&lt;/code&gt; 可以快速打开相关章节）。
  &lt;/li&gt;
  &lt;li&gt;
    高亮分组的帮助以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hl-&lt;/code&gt; 开头。如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h hl-WarningMsg&lt;/code&gt; 说的是警告信息分组的高亮。
  &lt;/li&gt;
  &lt;li&gt;
    语法高亮以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:syc-&lt;/code&gt; 开头，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :syn-conceal&lt;/code&gt; 讲的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:syn&lt;/code&gt; 命令的对于隐藏字符是如何显示的。
  &lt;/li&gt;
  &lt;li&gt;
    快速修复命令以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:c&lt;/code&gt; 开头，而位置列表命令以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:l&lt;/code&gt; 开头。
  &lt;/li&gt;
  &lt;li&gt;
    &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h BufWinLeave&lt;/code&gt; 讲的是 BufWinLeave 自动命令。还有，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h autocommand-events&lt;/code&gt; （译者注：原文是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h autocommands-events&lt;/code&gt;，但是没有该帮助）讲的是所有可用的事件。
  &lt;/li&gt;
  &lt;li&gt;
    启动参数都以“-”开头，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h -f&lt;/code&gt; 会告诉你 Vim 中 “-f” 参数的作用。
  &lt;/li&gt;
  &lt;li&gt;
    额外的特性都以“+”开头，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h +conceal&lt;/code&gt; 讲的是关于隐藏字符的支持。
  &lt;/li&gt;
  &lt;li&gt;
    错误代码可以在帮助系统中直接查到。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h E297&lt;/code&gt; 会带你到关于这一错误的详细解释。但是有时并没有转到错误描述，而是列出了经常导出这一错误的 Vim 命令，如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h E128&lt;/code&gt; （译者注：原文为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h hE128&lt;/code&gt;，但是并没有该帮助）会直接跳转到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:function&lt;/code&gt; 命令。
  &lt;/li&gt;
  &lt;li&gt;关于包含的语法文件的文档的帮助话题格式是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h ft-*-syntax&lt;/code&gt;。如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h ft-c-syntax&lt;/code&gt; 说的就是 C 语言语法文件以及它所提供的选项。有的语法文件还会带有自动完成（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h ft-php-omni&lt;/code&gt;）或文件类型插件（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h ft-tex-plugin&lt;/code&gt;）相关的章节可以查看。&lt;/li&gt;
&lt;/ol&gt;

另外在每个帮助页的顶端通常会包含一个用户文档链接（更多的从从用户的角度出发来主角命令的功能和用法，不涉及那么多细节）。如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h pattern.txt&lt;/code&gt; 里包含了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h 03.9&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h usr_27&lt;/code&gt; 两个章节的链接。

&lt;h3 id=&quot;获取在线帮助&quot;&gt;获取在线帮助&lt;/h3&gt;

如果你遇到了无法解决的问题，或者需要指引的话，可以参考 &lt;a href=&quot;https://groups.google.com/forum/#!forum/vim_use&quot;&gt;Vim 使用&lt;/a&gt;邮件列表。 &lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Relay_Chat&quot;&gt;IRC&lt;/a&gt; 也是一个很不错的资源。 &lt;a href=&quot;https://freenode.net/&quot;&gt;Freenode&lt;/a&gt; 上的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#vim&lt;/code&gt; 频道很庞大，并且里面有许多乐于助人的人。

如果你想给 Vim 提交 Bug 的话，可以使用 &lt;a href=&quot;https://groups.google.com/forum/#!forum/vim_dev&quot;&gt;vim_dev&lt;/a&gt; 邮件列表。

&lt;h3 id=&quot;执行自动命令&quot;&gt;执行自动命令&lt;/h3&gt;

你可以触发任何事件，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:doautocmd BufRead&lt;/code&gt;。

&lt;h4 id=&quot;用户自定义事件&quot;&gt;用户自定义事件&lt;/h4&gt;

对于插件而言，创建你自己的自定义事件有时非常有用。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; Chibby&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;&quot; A lot of stuff is happening here.&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;&quot; And at last..&lt;/span&gt;
    doautocmd &lt;span class=&quot;nb&quot;&gt;User&lt;/span&gt; ChibbyExit
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

现在你插件的用户可以在 Chibby 执行完成之后做任何他想做的事情：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;User&lt;/span&gt; ChibbyExit &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; ChibbyCleanup&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

顺便提一句，如果在使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:autocmd&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:doautocmd&lt;/code&gt; 时没有捕捉异常，那么会输出 “No matching autocommands” 信息。这也是为什么许多插件用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;silent doautocmd ...&lt;/code&gt; 的原因。但是这也会有不足，那就是你不能再在 :autocmd 中使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo &quot;foo&quot;&lt;/code&gt; 了，取而代之的是你要使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unsilent echo &quot;foo&quot;&lt;/code&gt; 来输出。

这就是为什么要在触发事件之前先判断事件是否存在的原因，

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;#User#ChibbyExit&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  doautocmd &lt;span class=&quot;nb&quot;&gt;User&lt;/span&gt; ChibbyExit
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

帮助文档：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h User&lt;/code&gt;

&lt;h4 id=&quot;事件嵌套&quot;&gt;事件嵌套&lt;/h4&gt;

默认情况下，自动命令不能嵌套！如果某个自动命令执行了一个命令，这个命令再依次触发其它的事件，这是不可能的。

例如你想在每次启动 Vim 的时候自动打开你的 vimrc 文件：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;VimEnter&lt;/span&gt; * &lt;span class=&quot;k&quot;&gt;edit&lt;/span&gt; $MYVIMRC
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当你启动 Vim 的时候，它会帮你打开你的 vimrc 文件，但是你很快会注意到这个文件没有任何的高亮，尽管平时它是正常可以高亮的。

问题在于你的非嵌套自动命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:edit&lt;/code&gt; 不会触发“BufRead”事件，所以并不会把文件类型设置成“vim”，进而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$VIMRUNTIME/syntax/vim.vim&lt;/code&gt; 永远不会被引入。详细信息请参考：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:au BufRead *.vim&lt;/code&gt;。要想完成上面所说的需求，使用下面这个命令：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;VimEnter&lt;/span&gt; * nested &lt;span class=&quot;k&quot;&gt;edit&lt;/span&gt; $MYVIMRC
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

帮助文档：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h autocmd-nested&lt;/code&gt;

&lt;h3 id=&quot;剪切板&quot;&gt;剪切板&lt;/h3&gt;

如果你想在没有 GUI 支持的 Unix 系统中使用 Vim 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;clipboard&apos;&lt;/code&gt; 选项，则需要 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+clipboard&lt;/code&gt; 以及可选的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+xterm_clipboard&lt;/code&gt; 两个&lt;a href=&quot;#what-kind-of-vim-am-i-running&quot;&gt;特性&lt;/a&gt;支持。

帮助文档：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;clipboard&apos;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;gui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;clipboard&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;gui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;selections
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

另外请参考：&lt;a href=&quot;#持续粘贴为什么我每次都要设置-paste-模式&quot;&gt;持续粘贴（为什么我每次都要设置 ‘paste’ 模式&lt;/a&gt;

&lt;h4 id=&quot;剪贴板的使用windows-osx&quot;&gt;剪贴板的使用（Windows, OSX）&lt;/h4&gt;

Windows 自带了&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/windows/desktop/ms649012(v=vs.85).aspx&quot;&gt;剪贴板&lt;/a&gt;，OSX 则带了一个&lt;a href=&quot;https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/PasteboardGuide106/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008100-SW1&quot;&gt;粘贴板&lt;/a&gt;

在这两个系统中都可以用大家习惯用的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctrl+c / cmd+c&lt;/code&gt; 复制选择的文本，然后在另外一个应用中用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctrl+v / cmd+v&lt;/code&gt; 进行粘贴。

需要注意的是复制的文本已经被发送到了剪贴板，所以你在粘贴复制的内容之前关闭这个应用是没有任何问题的。

每次复制的时候，都会向剪贴板寄存器 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; 中写入数据。 而在 Vim 中分别使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;*y&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;*p&lt;/code&gt; 来进行复制（yank) 和 粘贴（paste)。

如果你不想每次操作都要指定 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; 寄存器，可以在你的 vimrc 中添加如下配置：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;clipboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;unnamed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

通常情况下复制/删除/放入操作会往 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;&lt;/code&gt; 寄存器中写入数据，而加上了上面的配置之后 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; 寄存器也会被写入同样数据，因此简单的使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p&lt;/code&gt; 就可以复制粘贴了。

我再说一遍：使用上面的选项意味着每一次的复制/粘贴，即使在同一个 Vim 窗口里，都会修改剪贴板的内容。你自己决定上面的选项是否适合。

如果你觉得输入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; 还是太麻烦的话，可以使用下面的设置把在可视模式下选择的内容发送到剪贴板：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;clipboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;unnamed&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;autoselect
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;guioptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

帮助文档：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;clipboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;unnamed
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; autoselect
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;go_a&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;剪贴板的使用linux-bsd-&quot;&gt;剪贴板的使用（Linux, BSD, …）&lt;/h4&gt;

如果你的系统使用了 &lt;a href=&quot;http://www.x.org/wiki&quot;&gt;X 图形界面&lt;/a&gt;，事情会变得有一点不同。X 图形界面实现了 &lt;a href=&quot;http://www.x.org/releases/X11R7.7/doc/xproto/x11protocol.html&quot;&gt;X 窗口系统协议&lt;/a&gt;, 这个协议在 1987 年发布的主版本 11，因此 X 也通常被称为 X11。

在 X10 版本中，&lt;a href=&quot;http://www.x.org/releases/X11R7.7/doc/xorg-docs/icccm/icccm.html#Peer_to_Peer_Communication_by_Means_of_Cut_Buffers&quot;&gt;剪贴缓冲区&lt;/a&gt;被用来实现像 &lt;em&gt;clipboard&lt;/em&gt; 一样由 X 来复制文本，并且可以被所有的程序访问。现在这个机制在 X 中还存在，但是已经过时了，很多程序都不再使用这一机制。

近年来数据在程序之间是通过&lt;a href=&quot;http://www.x.org/releases/X11R7.7/doc/xorg-docs/icccm/icccm.html#Peer_to_Peer_Communication_by_Means_of_Selections&quot;&gt;选择&lt;/a&gt;进行传递的。一共有三种选择，经常用到的有两种：PRIMARY 和 CLIPBOARD。

选择的工作工模大致是这样的：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Program A：&amp;lt;ctrl+c&amp;gt;
Program A：声称对 CLIPBOARD 的所有权
Program B：&amp;lt;ctrl+v&amp;gt;
Program B：发现CLIPBOARD的所有权被Program A持有
Program B：从Program A请求数据
Program A：响应这个请求并发送数据给Program B
Program B：从Program A接收数据并插入到窗口中
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;选择&lt;/th&gt;
      &lt;th&gt;何时使用&lt;/th&gt;
      &lt;th&gt;如何粘贴&lt;/th&gt;
      &lt;th&gt;如何在 Vim 中访问&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;PRIMARY&lt;/td&gt;
      &lt;td&gt;选择文本&lt;/td&gt;
      &lt;td&gt;鼠标中键, shift+insert&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; 寄存器&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CLIPBOARD&lt;/td&gt;
      &lt;td&gt;选择文本并按 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctrl+c&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctrl+v&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;寄存器&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;strong&gt;注意&lt;/strong&gt;：X 服务器并不会保存选择（不仅仅是 CLIPBOARD 选择）！因此在关闭了相应的程序后，你用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctrl+c&lt;/code&gt; 复制的内容将丢失。

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;*p&lt;/code&gt; 来贴粘 PRIMARY 选择中的内容，或者使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;+y1G&lt;/code&gt; 来将整个文件的内容复制到 CLIPBOARD 选择。

如果你需要经常访问这两个寄存器，可以考虑使用如下配置：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;clipboard&lt;/span&gt;^&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;unnamed          &quot; * 寄存器
&lt;span class=&quot;c&quot;&gt;&quot; 或者&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;clipboard&lt;/span&gt;^&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;unnamedplus      &quot; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; 寄存器
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^=&lt;/code&gt; 用来将设置的值加到默认值之前，详见：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :set^=&lt;/code&gt;）

这会使得所有复制/删除/放入操作使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; 寄存器代替默认的未命令寄存器 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;&lt;/code&gt;。之后你就可以直接使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p&lt;/code&gt; 访问你的 X 选择了。

帮助文档：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;clipboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;unnamed
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;clipboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;unnamedplus
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;打开文件时恢复光标位置&quot;&gt;打开文件时恢复光标位置&lt;/h3&gt;

如果没有这个设置，每次打开文件时光标都将定位在第一行。而加入了这个设置以后，你就可以恢复到上次关闭文件时光标所在的位置了。

将下面的配置添加到你的 vimrc 文件：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;BufReadPost&lt;/span&gt; *
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&apos;\&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;nb&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&apos;\&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt;   exe &lt;span class=&quot;s2&quot;&gt;&quot;normal! g`\&quot;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;    \&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这是通过判断之前的光标位置是否存在（文件可能被其它程序修改而导致所记录的位置已经不存在了），如果存在的话就执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g`&quot;&lt;/code&gt; （转到你离开时的光标位置但是不更改跳转列表）。

这需要使用 viminfo 文件：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h viminfo-&lt;/code&gt;。

&lt;h3 id=&quot;临时文件&quot;&gt;临时文件&lt;/h3&gt;

根据选项的不同， Vim 最多会创建 4 种工作文件。

&lt;h4 id=&quot;备份文件&quot;&gt;备份文件&lt;/h4&gt;

你可以让 Vim 在将修改写入到文件之前先备份原文件。默认情况下， Vim 会保存一个备份文件但是当修改成功写入后会立即删除它（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set writebackup&lt;/code&gt;）。如果你想一直保留这个备份文件的话，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set backup&lt;/code&gt;。而如果你想禁用备份功能的话，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set nobackup nowritebackup&lt;/code&gt;。

咱们来看一下上次我在 vimrc 中改了什么：

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;diff ~/.vim/vimrc ~/.vim/files/backup/vimrc-vimbackup
390d389
&amp;lt; &lt;span class=&quot;nb&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-bar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-nargs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-complete&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;help &lt;/span&gt;H helpgrep &amp;lt;args&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

帮助文档：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h backup&lt;/code&gt;

&lt;h4 id=&quot;交换文件&quot;&gt;交换文件&lt;/h4&gt;

假设你有一个非常棒的科幻小说的构思。在按照故事情节已经写了好几个小时几十万字的时候..忽然停电了！而那时你才想起来你上次保存 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/来自外太空的邪恶入侵者.txt&lt;/code&gt; 是在.. 好吧，你从来没有保存过。

但是并非没有希望了！在编辑某个文件的时候， Vim 会创建一个交换文件，里面保存的是对当前文件所有未保存的修改。自己试一下，打开任意的文件，并使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:swapname&lt;/code&gt; 获得当前的交换文件的保存路径。你也可以将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set noswapfile&lt;/code&gt; 加入到 vimrc 中来禁用交换文件。

默认情况下，交换文件会自动保存在被编辑文件所在的目录下，文件名以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.file.swp&lt;/code&gt; 后缀结尾，每当你修改了超过 200 个字符或是在之前 4 秒内没有任何动作时更新它的内容，在你不再编辑这个文件的时候会被删除。你可以自己修改这些数字，详见：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;updatecount&apos;&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;updatetime&apos;&lt;/code&gt;。

而在断电时，交换文件并不会被删除。当你再次打开 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim ~/来自外太空的邪恶入侵者.txt&lt;/code&gt; 时， Vim 会提示你恢复这个文件。

帮助文档：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h swap-file&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h usr_11&lt;/code&gt;

&lt;h4 id=&quot;撤销文件&quot;&gt;撤销文件&lt;/h4&gt;

&lt;a href=&quot;#%E5%86%85%E5%AE%B9%E5%8F%98%E6%9B%B4%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95&quot;&gt;内容变更历史记录&lt;/a&gt;是保存在内存中的，并且会在 Vim 退出时清空。如果你想让它持久化到磁盘中，可以设置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set undofile&lt;/code&gt;。这会把文件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/foo.c&lt;/code&gt; 的撤销文件保存在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/foo.c.un~&lt;/code&gt;。

帮助文档：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;undofile&apos;&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h undo-persistence&lt;/code&gt;

&lt;h4 id=&quot;viminfo-文件&quot;&gt;viminfo 文件&lt;/h4&gt;

备份文件、交换文件和撤销文件都是与文本状态相关的，而 viminfo 文件是用来保存在 Vim 退出时可能会丢失的其它的信息的。包括历史记录（命令历史、搜索历史、输入历史）、寄存器内容、标注、缓冲区列表、全局变量等等。

默认情况下，viminfo 被保存在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.viminfo&lt;/code&gt;。

帮助文档：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h viminfo&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;viminfo&apos;&lt;/code&gt;

&lt;h4 id=&quot;临时文件管理设置示例&quot;&gt;临时文件管理设置示例&lt;/h4&gt;

如果你跟我一样，也喜欢把这些文件放到一个位置（如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.vim/files&lt;/code&gt;）的话，可以使用下面的配置：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot; 如果文件夹不存在，则新建文件夹&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;isdirectory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;$HOME&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;/.vim/files&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;nb&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;*mkdir&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;$HOME&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;/.vim/files&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&quot; 备份文件&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;backup&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;backupdir&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;$HOME&lt;span class=&quot;sr&quot;&gt;/.vim/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/backup/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;backupext&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;=-&lt;/span&gt;vimbackup
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;backupskip&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; 交换文件&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;directory&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;$HOME&lt;span class=&quot;sr&quot;&gt;/.vim/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/swap/&lt;/span&gt;/
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;updatecount&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; 撤销文件&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;undofile&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;undodir&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;$HOME&lt;span class=&quot;sr&quot;&gt;/.vim/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/undo/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; viminfo 文件&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;viminfo&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&apos;&lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;n&lt;/span&gt;$HOME&lt;span class=&quot;sr&quot;&gt;/.vim/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/info/&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;viminfo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

注意：如果你在一个多用户系统中编辑某个文件时， Vim 提示你交换文件已经存在的话，可能是因为有其他的用户此时正在编辑这个文件。而如果将交换文件放到自己的 home 目录的话，这个功能就失效了。因此服务器非常不建议将这些文件修改到 HOME 目录，避免多人同时编辑一个文件，却没有任何警告。

&lt;h3 id=&quot;编辑远程文件&quot;&gt;编辑远程文件&lt;/h3&gt;

Vim 自带的 netrw 插件支持对远程文件的编辑。实际上它将远程的文件通过 scp 复制到本地的临时文件中，再用那个文件打开一个缓冲区，然后在保存时把文件再复制回远程位置。

下面的命令在你本地的 VIM 配置与 SSH 远程服务器上管理员想让你使用的配置有冲突时尤其有用：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;scp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;//&lt;/span&gt;bram@awesome&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;site&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;com&lt;/span&gt;/&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;vimrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果你已经设置了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.ssh/config&lt;/code&gt;，SSH 会自动读取这里的配置：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Host awesome
    HostName awesome.site.com
    Port 1234
    User bram
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果你的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.ssh/config&lt;/code&gt; 中有以上的内容，那么下面的命令就可以正常执行了：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;scp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;//&lt;/span&gt;awesome/&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;vimrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

可以用同样的方法编辑 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.netrc&lt;/code&gt;, 详见：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h netrc-netrc&lt;/code&gt;。

确保你已经看过了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h netrw-ssh-hack&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h g:netrw_ssh_cmd&lt;/code&gt;。

另外一种编辑远程文件的方法是使用 &lt;a href=&quot;https://wiki.archlinux.org/index.php/Sshfs&quot;&gt;sshfs&lt;/a&gt;，它会用 &lt;a href=&quot;https://en.wikipedia.org/wiki/Filesystem_in_Userspace&quot;&gt;FUSE&lt;/a&gt; 来挂载远程的文件系统到你本地的系统当中。

&lt;h3 id=&quot;插件管理&quot;&gt;插件管理&lt;/h3&gt;

&lt;a href=&quot;https://github.com/tpope/vim-pathogen&quot;&gt;Pathogen&lt;/a&gt;是第一个比较流行的插件管理工具。实际上它只是修改了 &lt;em&gt;runtimepath&lt;/em&gt; （&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;rtp&apos;&lt;/code&gt;） 来引入所有放到该目录下的文件。你需要自己克隆插件的代码仓库到那个目录。

真正的插件管理工具会在 Vim 中提供帮助你安装或更新插件的命令。以下是一些常用的插件管理工具：

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Shougo/dein.vim&quot;&gt;dein&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/junegunn/vim-plug&quot;&gt;plug&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/MarcWeber/vim-addon-manager&quot;&gt;vim-addon-manager&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/VundleVim/Vundle.vim&quot;&gt;vundle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;多行编辑&quot;&gt;多行编辑&lt;/h3&gt;

这是一种可以同时输入多行连续文本的技术。参考这个&lt;a href=&quot;https://raw.githubusercontent.com/mhinz/vim-galore/master/contents/images/content-block_insert.gif&quot;&gt;示例&lt;/a&gt;。

用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-v&amp;gt;&lt;/code&gt; 切换到可视块模式。然后向下选中几行，按 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;I&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; （译者注：大写字母，即 shift+i 或 shift+a）然后开始输入你想要输入的文本。

在刚开始的时候可能会有些迷惑，因为文本只出现在了当前编辑的行，只有在当前的插入动作结束后，之前选中的其它行才会出现插入的文本。

举一个简单的例子：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-v&amp;gt;3jItext&amp;lt;esc&amp;gt;&lt;/code&gt;。

如果你要编辑的行长度不同，但是你想在他们后面追加相同的内容的话，可以试一下这个：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-v&amp;gt;3j$Atext&amp;lt;esc&amp;gt;&lt;/code&gt;。

有时你可能需要把光标放到当前行末尾之后，默认情况下你是不可能做到的，但是可能通过设置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virtualedit&lt;/code&gt; 选项达到目的：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;virtualedit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

设置之后 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$10l&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;90|&lt;/code&gt; 都会生效，即使超过了行尾的长度。

详见 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h blockwise-examples&lt;/code&gt;。在开始的时候可能会觉得有些复杂，但是它很快就会成为你的第二天性的。

如果你想探索更有趣的事情，可以看看&lt;a href=&quot;https://github.com/terryma/vim-multiple-cursors&quot;&gt;多光标&lt;/a&gt;

&lt;h3 id=&quot;使用外部程序和过滤器&quot;&gt;使用外部程序和过滤器&lt;/h3&gt;

免责声明：Vim 是单线程的，因此在 Vim 中以前端进程执行其它的程序时会阻止其它的一切。当然你可以使用 Vim 程序接口，如 Lua，并且使用它的多线程支持，但是在那期间， Vim 的处理还是被阻止了。Neovim 添加了任务 API 解决了此问题。

（据说 Bram 正在考虑在 Vim 中也添加任务控制。如果你使用了较新版本的的 Vim ，可以看一下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:helpgrep startjob&lt;/code&gt;。）

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:!&lt;/code&gt; 启动一个新任务。如果你想列出当前工作目录下的所有文件，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:!ls&lt;/code&gt;。 用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt; 来将结果通过管道重定向，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:!ls -l | sort | tail -n5&lt;/code&gt;。

没有使用范围时（译者注：范围就是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt; 之间的内容，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt; 表示当前行，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+4&lt;/code&gt; 表示向下偏移 4 行，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt; 表示最末行等，多行时用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;,&lt;/code&gt; 将它们分开，如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.,$&lt;/code&gt; 表示从当前行到末行），&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:!&lt;/code&gt; 会显示在一个可滚动的窗口中（译者注：在 GVim 和在终端里运行的结果稍有不同）。相反的，如果指定了范围，这些行会被&lt;a href=&quot;https://en.wikipedia.org/wiki/Filter_(software)&quot;&gt;过滤&lt;/a&gt;。这意味着它们会通过管道被重定向到过滤程序的 &lt;a href=&quot;https://en.wikipedia.org/wiki/Standard_streams#Standard_input_.28stdin.29&quot;&gt;stdin&lt;/a&gt;，在处理后再通过过滤程序的 &lt;a href=&quot;https://en.wikipedia.org/wiki/Standard_streams#Standard_output_.28stdout.29&quot;&gt;stdout&lt;/a&gt; 输出，用输出结果替换范围内的文本。例如：为接下来的 5 行文本添加行号，可以使用：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:.,+&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;nl &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ba&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;w1 &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;s&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

由于手动添加范围很麻烦， Vim 提供了一些辅助方法以方便的添加范围。如果需要经常带着范围的话，你可以在可见模式中先选择，然后再按 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt; （译者注：选中后再按 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt; 更方便）。还可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt; 来取用一个 motion 的范围，如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!ipsort&lt;/code&gt; （译者注：原文为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!ip!sort&lt;/code&gt; ，但经过实验发现该命令执行报错，可能是因为 Vim 版本的原因造成的，新版本使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ip&lt;/code&gt; 选择当前段落后自动在命令后添加了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt; ，按照作者的写法来看，可能之前的版本没有自动添加 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt; ）可以将当前段落的所有行按字母表顺序进行排序。

一个使用过滤器比较好的案例是&lt;a href=&quot;https://golang.org/&quot;&gt;Go 语言&lt;/a&gt;。它的缩进语法非常个性，甚至还专门提供了一个名为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gofmt&lt;/code&gt; 的过滤器来对 Go 语言的源文件进行正确的缩进。Go 语言的插件通常会提供一个名为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Fmt&lt;/code&gt; 的函数，这个函数就是执行了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:%!gofmt&lt;/code&gt; 来对整个文件进行缩进。

人们常用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:r !prog&lt;/code&gt; 将 prog 程序的插入放到当前行的下面，这对于脚本来说是很不错的选择，但是在使用的过程中我发现 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!!ls&lt;/code&gt; 更加方便，它会用输出结果替换当前行的内容。（译者注：前面命令中的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prog&lt;/code&gt; 只是个占位符，在实际使用中需要替换成其它的程序，如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:r !ls&lt;/code&gt;，这就与后面的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!!ls&lt;/code&gt; 相对应了，两者唯一的不同是第一个命令不会覆盖当前行内容，但是第二个命令会）

帮助文档：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;filter&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;cscope&quot;&gt;Cscope&lt;/h3&gt;

&lt;a href=&quot;http://cscope.sourceforge.net/&quot;&gt;Cscope&lt;/a&gt; 的功能比 &lt;a href=&quot;http://ctags.sourceforge.net/&quot;&gt;ctags&lt;/a&gt; 要完善，但是只支持 C（通过设置 cscope.files 后同样支持 C++以及 Java）。

鉴于 Tag 文件只是知道某个符号是在哪里定义的，cscope 的数据库里的数据信息就多的多了：

&lt;ul&gt;
  &lt;li&gt;符号是在哪里定义的？&lt;/li&gt;
  &lt;li&gt;符号是在哪里被使用的？&lt;/li&gt;
  &lt;li&gt;这个全局符号定义了什么？&lt;/li&gt;
  &lt;li&gt;这个变量是在哪里被赋值的？&lt;/li&gt;
  &lt;li&gt;这个函数在源文件的哪个位置？&lt;/li&gt;
  &lt;li&gt;哪些函数调用了这个函数？&lt;/li&gt;
  &lt;li&gt;这个函数调用了哪些函数？&lt;/li&gt;
  &lt;li&gt;“out of space”消息是从哪来的？&lt;/li&gt;
  &lt;li&gt;在目录结构中当前的源文件在哪个位置？&lt;/li&gt;
  &lt;li&gt;哪些文件引用了这个头文件？&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;1-构建数据库&quot;&gt;1. 构建数据库&lt;/h4&gt;

在你项目的根目录执行下面的命令：

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cscope &lt;span class=&quot;nt&quot;&gt;-bqR&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这条命令会在当前目录下创建三个文件：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cscope{,.in,.po}.out&lt;/code&gt; 。把它们想象成你的数据库。

不幸的时 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cscope&lt;/code&gt; 默认只分析 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.[c|h|y|l]&lt;/code&gt; 文件。如果你想在 Java 项目中使用 cscope ，需要这样做：

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*.java&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; cscope.files
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cscope &lt;span class=&quot;nt&quot;&gt;-bq&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;2-添加数据库&quot;&gt;2. 添加数据库&lt;/h4&gt;

打开你新创建的数据库连接：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cs&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;cscope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;out
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

检查连接已经创建成功：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cs&lt;/span&gt; show
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

（当然你可以添加多个连接。）

&lt;h4 id=&quot;3-查询数据库&quot;&gt;3. 查询数据库&lt;/h4&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cs&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;kind&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;query&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:cs find d foo&lt;/code&gt; 会列出 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo(...)&lt;/code&gt; 调用的所有函数。

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Kind&lt;/th&gt;
      &lt;th&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;s&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;s&lt;/strong&gt;ymbol：查找使用该符号的引用&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;g&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;g&lt;/strong&gt;lobal：查找该全局符号的定义&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;c&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;c&lt;/strong&gt;alls：查找调用当前方法的位置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;t&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;t&lt;/strong&gt;ext：查找出现该文本的位置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;e&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;e&lt;/strong&gt;grep：使用 egrep 搜索当前单词&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;f&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;f&lt;/strong&gt;ile：打开文件名&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;i&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;i&lt;/strong&gt;ncludes：查询引入了当前文件的文件&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;d&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;d&lt;/strong&gt;epends：查找当前方法调用的方法&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

推荐一些比较方便的映射，如：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cs&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cscope&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;find&lt;/span&gt; s  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;cword&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cg&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cscope&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;g&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;cword&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cscope&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;cword&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;ct &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cscope&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;t&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;cword&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ce&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cscope&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;e&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;cword&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cscope&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;f&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;cfile&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ci&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cscope&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;i&lt;/span&gt; ^&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;cfile&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;$&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cscope&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;d&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;cword&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

所以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:tag&lt;/code&gt; （或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-]&amp;gt;&lt;/code&gt;）跳转到标签定义的文件，而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:cstag&lt;/code&gt; 可以达到同样的目的，同时还会打开 cscope 的数据库连接。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;cscopetag&apos;&lt;/code&gt; 选项使得 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:tag&lt;/code&gt; 命令自动的像 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:cstag&lt;/code&gt; 一样工作。这在你已经使用了基于标签的映射时会非常方便。

帮助文档：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h cscope&lt;/code&gt;

&lt;h3 id=&quot;matchit&quot;&gt;MatchIt&lt;/h3&gt;

由于 Vim 是用 C 语言编写的，因此许多功能都假设使用类似 C 语言的语法。默认情况下，如果你的光标在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#endif&lt;/code&gt; , 就可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt; 跳转到与之匹配的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;}&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#ifdef&lt;/code&gt;。

Vim 自带了一个名为 matchit.vim 的插件，但是默认没有启用。启用后可以用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt; 在 HTML 相匹配的标签或 VimL 的 if/else/endif 块之间进行跳转，它还带来了一些新的命令。

&lt;h4 id=&quot;在-vim-8-中安装&quot;&gt;在 Vim 8 中安装&lt;/h4&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot; vimrc&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;packadd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; matchit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;在-vim-7-或者更早的版本中安装&quot;&gt;在 Vim 7 或者更早的版本中安装&lt;/h4&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot;vimrc&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;runtime&lt;/span&gt; macros/matchit&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;vim&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

由于 matchit 的文档很全面，我建议安装以后执行一次下面的命令：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/.vim/&lt;/span&gt;doc
&lt;span class=&quot;p&quot;&gt;:!&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cp&lt;/span&gt; $VIMRUNTIME&lt;span class=&quot;sr&quot;&gt;/macros/&lt;/span&gt;matchit&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;vim&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/.vim/&lt;/span&gt;doc
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;helptags&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/.vim/&lt;/span&gt;doc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;简短的介绍&quot;&gt;简短的介绍&lt;/h4&gt;

至此这个插件已经可以使用了。 参考 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h matchit-intro&lt;/code&gt; 来获得支持的命令以及 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h matchit-languages&lt;/code&gt; 来获得支持的语言。

你可以很方便的定义自己的匹配对，如：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;FileType&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:match_words&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\&amp;lt;if\&amp;gt;:\&amp;lt;elif\&amp;gt;:\&amp;lt;else\&amp;gt;&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

之后你就可以在任何的 Python 文件中使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt; （向前）或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g%&lt;/code&gt; （向后）在这三个片断之间跳转了。

帮助文档：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; matchit&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;install
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; matchit
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:match_words&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;技巧&quot;&gt;技巧&lt;/h2&gt;

&lt;h3 id=&quot;跳至选择的区域另一端&quot;&gt;跳至选择的区域另一端&lt;/h3&gt;

在使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;V&lt;/code&gt; 选择某段文字后，可以用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;o&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;O&lt;/code&gt; 按键跳至选择区域的开头或者结尾。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:h v_o
:h v_O
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;聪明地使用-n-和-n&quot;&gt;聪明地使用 n 和 N&lt;/h3&gt;

&lt;kbd&gt;n&lt;/kbd&gt; 与 &lt;kbd&gt;N&lt;/kbd&gt; 的实际跳转方向取决于使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; 还是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt; 来执行搜索，其中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; 是向后搜索，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt; 是向前搜索。一开始我（原作者）觉得这里很难理解。

如果你希望 &lt;kbd&gt;n&lt;/kbd&gt; 始终为向后搜索，&lt;kbd&gt;N&lt;/kbd&gt; 始终为向前搜索，那么只需要这样设置：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;expr&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;n&lt;/span&gt;  &lt;span class=&quot;s1&quot;&gt;&apos;Nn&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;searchforward&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;expr&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; N  &lt;span class=&quot;s1&quot;&gt;&apos;nN&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;searchforward&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;聪明地使用命令行历史&quot;&gt;聪明地使用命令行历史&lt;/h3&gt;

我（原作者）习惯用 &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;p&lt;/kbd&gt; 和 &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;n&lt;/kbd&gt; 来跳转到上一个/下一个条目。其实这个操作也可以用在命令行中，快速调出之前执行过的命令。

不仅如此，你会发现 &lt;kbd&gt;上&lt;/kbd&gt; 和 &lt;kbd&gt;下&lt;/kbd&gt; 其实更智能。如果命令行中已经存在了一些文字，我们可以通过按方向键来匹配已经存在的内容。比如，命令行中现在是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:echo&lt;/code&gt;，这时候我们按 &lt;kbd&gt;上&lt;/kbd&gt;，就会帮我们补全成 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:echo &quot;Vim rocks!&quot;&lt;/code&gt;（前提是，之前输入过这段命令）。

当然，Vim 用户都不愿意去按方向键，事实上我们也不需要去按，只需要设置这样的映射：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;down&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
cnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;up&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这个功能，我（原作者）每天都要用很多次。

&lt;h3 id=&quot;智能-ctrl-l&quot;&gt;智能 Ctrl-l&lt;/h3&gt;

&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;l&lt;/kbd&gt; 的默认功能是清空并「重新绘制」当前的屏幕，就和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:redraw!&lt;/code&gt; 的功能一样。下面的这个映射就是执行重新绘制，并且取消通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt; 匹配字符的高亮，而且还可以修复代码高亮问题（有时候，由于多个代码高亮的脚本重叠，或者规则过于复杂，Vim 的代码高亮显示会出现问题）。不仅如此，还可以刷新「比较模式」（请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:help diff-mode&lt;/code&gt;）的代码高亮：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;nohlsearch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;diffupdate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;syntax&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sync&lt;/span&gt; fromstart&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;禁用错误报警声音和图标&quot;&gt;禁用错误报警声音和图标&lt;/h3&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;noerrorbells&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;novisualbell&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;t_vb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

请参阅 &lt;a href=&quot;http://vim.wikia.com/wiki/Disable_beeping&quot;&gt;Vim Wiki: Disable beeping&lt;/a&gt;。

&lt;h3 id=&quot;快速移动当前行&quot;&gt;快速移动当前行&lt;/h3&gt;

有时，我（原作者）想要快速把当前行上移或下移一行，只需要这样设置映射：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nnoremap &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;e&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;:&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;move -1-&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;count1&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;e&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;:&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;move +&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;count1&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这个映射，同样可以搭配数字使用，比如连续按下 &lt;kbd&gt;2&lt;/kbd&gt; &lt;kbd&gt;]&lt;/kbd&gt; &lt;kbd&gt;e&lt;/kbd&gt; 就可以把当前行向下移动两行。

&lt;h3 id=&quot;快速添加空行&quot;&gt;快速添加空行&lt;/h3&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nnoremap &lt;span class=&quot;p&quot;&gt;[&amp;lt;&lt;/span&gt;space&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;:&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;repeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nr2char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;count1&lt;span class=&quot;p&quot;&gt;)&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&apos;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;]&amp;lt;&lt;/span&gt;space&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;:&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;put&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;repeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nr2char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;count1&lt;span class=&quot;p&quot;&gt;)&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

设置之后，连续按下 &lt;kbd&gt;5&lt;/kbd&gt; &lt;kbd&gt;\[&lt;/kbd&gt; &lt;kbd&gt;空格&lt;/kbd&gt; 在当前行上方插入 5 个空行。

&lt;h4 id=&quot;运行时检测&quot;&gt;运行时检测&lt;/h4&gt;

需要的特性：+profile

Vim 提供了一个内置的运行时检查功能，能够找出运行慢的代码。

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:profile&lt;/code&gt; 命令后面跟着子命令来确定要查看什么。

如果你想查看所有的：

&lt;pre&gt;&lt;code class=&quot;language-Vim&quot;&gt;:profile start /tmp/profile.log
:profile file *
:profile func *
&amp;lt;do something in Vim&amp;gt;
&amp;lt;quit Vim&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

Vim 不断地在内存中检查信息，只在退出的时候输出出来。（Neovim 已经解决了这个问题用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:profile dump&lt;/code&gt; 命令）

看一下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/profile.log&lt;/code&gt; 文件，检查时运行的所有代码都会被显示出来，包括每一行代码运行的频率和时间。

大多数代码都是用户不熟悉的插件代码，如果你是在解决一个确切的问题，
直接跳到这个日志文件的末尾，那里有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FUNCTIONS SORTED ON TOTAL TIME&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FUNCTIONS SORTED ON SELF TIME&lt;/code&gt; 两个部分，如果某个 function 运行时间过长一眼就可以看到。

&lt;h4 id=&quot;查看启动时间&quot;&gt;查看启动时间&lt;/h4&gt;

感觉 Vim 启动的慢？到了研究几个数字的时候了：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;vim&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;--&lt;/span&gt;startuptime &lt;span class=&quot;sr&quot;&gt;/tmp/&lt;/span&gt;startup&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;q&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;k&quot;&gt;vim&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/tmp/&lt;/span&gt;startup&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

第一栏是最重要的因为它显示了&lt;strong&gt;绝对运行时间&lt;/strong&gt;，如果在前后两行之间时间差有很大的跳跃，那么是第二个文件太大或者含有需要检查的错误的 VimL 代码。

&lt;h3 id=&quot;nul-符用新行表示&quot;&gt;NUL 符用新行表示&lt;/h3&gt;

文件中的 NUL 符 （&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\0&lt;/code&gt;），在内存中被以新行（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\n&lt;/code&gt;）保存，在缓存空间中显示为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^@&lt;/code&gt;。

更多信息请参看 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man 7 ascii&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h NL-used-for-Nul&lt;/code&gt; 。

&lt;h3 id=&quot;快速编辑自定义宏&quot;&gt;快速编辑自定义宏&lt;/h3&gt;

这个功能真的很实用！下面的映射，就是在一个新的命令行窗口中读取某一个寄存器（默认为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;）。当你设置完成后，只需要按下 &lt;kbd&gt;回车&lt;/kbd&gt; 即可让它生效。

在录制宏的时候，我经常用这个来更改拼写错误。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;m&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;:&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;let @&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;register &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos; = &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;getreg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;register&lt;span class=&quot;p&quot;&gt;))&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

只需要连续按下 &lt;kbd&gt;leader&lt;/kbd&gt; &lt;kbd&gt;m&lt;/kbd&gt; 或者 &lt;kbd&gt;&quot;&lt;/kbd&gt; &lt;kbd&gt;leader&lt;/kbd&gt; &lt;kbd&gt;m&lt;/kbd&gt; 就可以调用了。

请注意，这里之所以要写成 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-r&amp;gt;&amp;lt;c-r&amp;gt;&lt;/code&gt; 是为了确保 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-r&amp;gt;&lt;/code&gt; 执行了。请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h c_^R^R&lt;/code&gt;

&lt;h3 id=&quot;快速跳转到源头文件&quot;&gt;快速跳转到源(头)文件&lt;/h3&gt;

这个技巧可以用在多种文件类型中。当你从源文件或者头文件中切换到其他文件的时候，这个技巧可以设置「文件标记」（请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h marks&lt;/code&gt;），然后你就可以通过连续按下 &lt;kbd&gt;&apos;&lt;/kbd&gt; &lt;kbd&gt;C&lt;/kbd&gt; 或者 &lt;kbd&gt;&apos;&lt;/kbd&gt; &lt;kbd&gt;H&lt;/kbd&gt; 快速跳转回去（请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;A&lt;/code&gt;）。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;BufLeave&lt;/span&gt; *&lt;span class=&quot;p&quot;&gt;.{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cpp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mark&lt;/span&gt; C
autocmd &lt;span class=&quot;nb&quot;&gt;BufLeave&lt;/span&gt; *&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;h&lt;/span&gt;       &lt;span class=&quot;k&quot;&gt;mark&lt;/span&gt; H
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;strong&gt;注意&lt;/strong&gt;：由于这个标记是设置在 viminfo 文件中，因此请先确认 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set viminfo?&lt;/code&gt; 中包含了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h viminfo-&apos;&lt;/code&gt;。

&lt;h3 id=&quot;在-gui-中快速改变字体大小&quot;&gt;在 GUI 中快速改变字体大小&lt;/h3&gt;

印象中，我（原作者）记得一下代码是来自 tpope’s 的配置文件：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;command&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; Bigger  &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;guifont&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;substitute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;amp;&lt;span class=&quot;nb&quot;&gt;guifont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\d\+$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\=submatch(0)+1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
command&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; Smaller &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;guifont&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;substitute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&amp;amp;&lt;span class=&quot;nb&quot;&gt;guifont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\d\+$&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\=submatch(0)-1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;根据模式改变光标类型&quot;&gt;根据模式改变光标类型&lt;/h3&gt;

我（原作者）习惯在普通模式下用块状光标，在插入模式下用条状光标（形状类似英文 “I” 的样子），然后在替换模式中使用下划线形状的光标。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;$TMUX&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;t_SI&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;\&amp;lt;Esc&amp;gt;]50;CursorShape=1\x7&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;t_EI&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;\&amp;lt;Esc&amp;gt;]50;CursorShape=0\x7&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;t_SR&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;\&amp;lt;Esc&amp;gt;]50;CursorShape=2\x7&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;t_SI&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;\&amp;lt;Esc&amp;gt;Ptmux;\&amp;lt;Esc&amp;gt;\&amp;lt;Esc&amp;gt;]50;CursorShape=1\x7\&amp;lt;Esc&amp;gt;\\&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;t_EI&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;\&amp;lt;Esc&amp;gt;Ptmux;\&amp;lt;Esc&amp;gt;\&amp;lt;Esc&amp;gt;]50;CursorShape=0\x7\&amp;lt;Esc&amp;gt;\\&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;t_SR&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;\&amp;lt;Esc&amp;gt;Ptmux;\&amp;lt;Esc&amp;gt;\&amp;lt;Esc&amp;gt;]50;CursorShape=2\x7\&amp;lt;Esc&amp;gt;\\&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

原理很简单，就是让 Vim 在进入和离开插入模式的时候，输出一些序列，请参考 &lt;a href=&quot;https://en.wikipedia.org/wiki/Escape_sequence&quot;&gt;escape sequence&lt;/a&gt;。Vim 与终端之间的中间层，比如 &lt;a href=&quot;https://tmux.github.io&quot;&gt;tmux&lt;/a&gt; 会处理并执行上面的代码。

但上面这个还是有一个缺点的。终端环境的内部原理不尽相同，对于序列的处理方式也稍有不同。因此，上面的代码可能无法在你的环境中运行。甚至，你的运行环境也有可能不支持其他光标形状，请参阅你的 Vim 运行环境的文档。

好消息是，上面这个代码，可以在 iTerm2 中完美运行。

&lt;h3 id=&quot;防止水平滑动的时候失去选择&quot;&gt;防止水平滑动的时候失去选择&lt;/h3&gt;

如果你选中了一行或多行，那么你可以用 &lt;kbd&gt;&amp;lt;&lt;/kbd&gt; 或 &lt;kbd&gt;&amp;gt;&lt;/kbd&gt; 来调整他们的缩进。但在调整之后就不会保持选中状态了。

你可以连续按下 &lt;kbd&gt;g&lt;/kbd&gt; &lt;kbd&gt;v&lt;/kbd&gt; 来重新选中他们，请参考 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h gv&lt;/code&gt;。因此，你可以这样来配置映射：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;xnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;gv
xnoremap &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;gv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

设置好之后，在可视模式中使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; 就不会再出现上面提到的问题了。

&lt;h3 id=&quot;选择当前行至结尾排除换行符&quot;&gt;选择当前行至结尾，排除换行符&lt;/h3&gt;

在 Vim 里，我们可以同过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v$&lt;/code&gt; 选择当前行至结尾，但此时会把最后一个换行符也选中，通常需要按额外的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h&lt;/code&gt; 来取消最后选中最后一个换行符号。
Vim 提供了一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g_&lt;/code&gt; 快捷键，可以移动光标至最后一个非空字符。因此，为达到次效果，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vg_&lt;/code&gt;。当然，如果觉得按三个键比较麻烦，
可以添加一个映射：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nnoremap L g_
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这样就可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vL&lt;/code&gt; 达到一样的效果了。

&lt;h3 id=&quot;重新载入保存文件&quot;&gt;重新载入保存文件&lt;/h3&gt;

通过&lt;a href=&quot;#自动命令&quot;&gt;自动命令&lt;/a&gt;，你可以在保存文件的同时触发一些其他功能。比如，如果这个文件是一个配置文件，那么就重新载入；或者你还可以对这个文件进行代码风格检查。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;BufWritePost&lt;/span&gt; $MYVIMRC &lt;span class=&quot;k&quot;&gt;source&lt;/span&gt; $MYVIMRC
autocmd &lt;span class=&quot;nb&quot;&gt;BufWritePost&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/.Xdefaults call system(&apos;xrdb ~/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;Xdefaults&apos;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;更加智能的当前行高亮&quot;&gt;更加智能的当前行高亮&lt;/h3&gt;

我（原作者）很喜欢「当前行高亮」（请参阅 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h cursorline&lt;/code&gt;）这个功能，但我只想让这个效果出现在当前窗口，而且在插入模式中关闭这个效果：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;InsertLeave&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;WinEnter&lt;/span&gt; * &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cursorline&lt;/span&gt;
autocmd &lt;span class=&quot;nb&quot;&gt;InsertEnter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;WinLeave&lt;/span&gt; * &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nocursorline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;更快的关键字补全&quot;&gt;更快的关键字补全&lt;/h3&gt;

关键字补全（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-n&amp;gt;&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;c-p&amp;gt;&lt;/code&gt;）功能的工作方式是，无论 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;complete&apos;&lt;/code&gt; 设置中有什么，它都会尝试着去补全。这样，一些我们用不到的标签也会出现在补全列表中。而且，它会扫描很多文件，有时候运行起来非常慢。如果你不需要这些，那么完全可以像这样把它们禁用掉：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;i&lt;/span&gt;   &quot; disable scanning included &lt;span class=&quot;k&quot;&gt;files&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;t&lt;/span&gt;   &quot; disable searching &lt;span class=&quot;k&quot;&gt;tags&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;改变颜色主题的默认外观&quot;&gt;改变颜色主题的默认外观&lt;/h3&gt;

如果你想让状态栏在颜色主题更改后依然保持灰色，那么只需要这样设置：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;ColorScheme&lt;/span&gt; * &lt;span class=&quot;nb&quot;&gt;highlight&lt;/span&gt; StatusLine ctermbg&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;darkgray cterm&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NONE&lt;/span&gt; guibg&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;darkgray &lt;span class=&quot;k&quot;&gt;gui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NONE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

同理，如果你想让某一个颜色主题（比如 “lucius”）的状态栏为灰色（请使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:echo color_name&lt;/code&gt; 来查看当前可用的所有颜色主题）：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;ColorScheme&lt;/span&gt; lucius &lt;span class=&quot;nb&quot;&gt;highlight&lt;/span&gt; StatusLine ctermbg&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;darkgray cterm&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NONE&lt;/span&gt; guibg&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;darkgray &lt;span class=&quot;k&quot;&gt;gui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NONE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;命令&quot;&gt;命令&lt;/h3&gt;

下面的命令都比较有用，最好了解一下。用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :&amp;lt;command name&amp;gt;&lt;/code&gt; 来了解更多关于它们的信息，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :global&lt;/code&gt;。

&lt;h4 id=&quot;global-和-vglobal---在所有匹配行执行命令&quot;&gt;:global 和 :vglobal - 在所有匹配行执行命令&lt;/h4&gt;

在所有符合条件的行上执行某个命令。如： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:global /regexp/ print&lt;/code&gt; 会在所有包含 “regexp” 的行上执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print&lt;/code&gt; 命令（译者注：regexp 有正则表达式的意思，该命令同样支持正则表达式，在所有符合正则表达式的行上执行指定的命令）。

趣闻：你们可能都知道老牌的 grep 命令，一个由 Ken Thompson 编写的过滤程序。它是干什么用的呢？它会输出所有匹配指定正则表达式的行！现在猜一下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:global /regexp/ print&lt;/code&gt; 的简写形式是什么？没错！就是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:g/re/p&lt;/code&gt; 。 Ken Thompsom 在编写 grep 程序的时候是受了 vi &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:global&lt;/code&gt; 的启发。（译者注： &lt;a href=&quot;https://robots.thoughtbot.com/how-grep-got-its-name）&quot;&gt;https://robots.thoughtbot.com/how-grep-got-its-name）&lt;/a&gt;

既然它的名字是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:global&lt;/code&gt;，理应仅作用在所有行上，但是它也是可以带范围限制的。假设你想使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:delete&lt;/code&gt; 命令删除从当前行到下一个空行（由正则表达式 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^$&lt;/code&gt; 匹配）范围内所有包含 “foo” 的行：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:,&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/^$/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/foo/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果要在所有 &lt;em&gt;不&lt;/em&gt; 匹配的行上执行命令的话，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:global!&lt;/code&gt; 或是它的别名 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:vglobal&lt;/code&gt; （ V 代表的是 inVerse ）。

&lt;h4 id=&quot;normal-和-execute---脚本梦之队&quot;&gt;:normal 和 :execute - 脚本梦之队&lt;/h4&gt;

这两个命令经常在 Vim 的脚本里使用。

借助于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:normal&lt;/code&gt; 可以在命令行里进行普通模式的映射。如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:normal! 4j&lt;/code&gt; 会令光标下移 4 行（由于加了”!”，所以不会使用自定义的映射 “j”）。

需要注意的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:normal&lt;/code&gt; 同样可以使用范围数（译者注：参考 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h range&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :normal-range&lt;/code&gt; 了解更多），故 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:%norm! Iabc&lt;/code&gt; 会在所有行前加上 “abc”。

借助于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:execute&lt;/code&gt; 可以将命令和表达式混合在一起使用。假设你正在编辑一个 C 语言的文件，想切换到它的头文件：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;edit&apos;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fnamemodify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;%&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;:r&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;.h&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

（译者注：头文件为与与源文件同名但是扩展名为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.h&lt;/code&gt; 的文件。上面的命令中 expand 获得当前文件的名称，fnamemodify 获取不带扩展名的文件名，再连上 ‘.h’ 就是头文件的文件名了，最后在使用 edit 命令打开这个头文件。）

这两个命令经常一起使用。假设你想让光标下移 n 行：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;normal!&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;j&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;重定向消息&quot;&gt;重定向消息&lt;/h4&gt;

许多命令都会输出消息，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:redir&lt;/code&gt; 用来重定向这些消息。它可以将消息输出到文件、&lt;a href=&quot;#寄存器&quot;&gt;寄存器&lt;/a&gt;或是某个变量中。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot; 将消息重定向到变量 `neatvar` 中&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;redir&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; neatvar
&lt;span class=&quot;c&quot;&gt;&quot; 打印所有寄存器的内容&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;reg&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; 结束重定向&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;redir&lt;/span&gt; END
&lt;span class=&quot;c&quot;&gt;&quot; 输出变量&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;echo neatvar
&lt;span class=&quot;c&quot;&gt;&quot; 恶搞一下，我们把它输出到当前缓冲区&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;put&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;neatvar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

再 Vim 8 中，可以更简单的方式即位：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:put =execute(&apos;reg&apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

（译者注：原文最后一条命令是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:put =nicevar&lt;/code&gt; 但是实际会报变量未定义的错误）
（实测 neovim/vim8 下没问题）

帮助文档：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :redir&lt;/code&gt;

&lt;h2 id=&quot;调试&quot;&gt;调试&lt;/h2&gt;

&lt;h3 id=&quot;常规建议&quot;&gt;常规建议&lt;/h3&gt;

如果你遇到了奇怪的行为，尝试用这个命令重现它：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim -u NONE -N
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这样会在不引用 vimrc（默认设置）的情况下重启 vim，并且在 &lt;strong&gt;nocompatible&lt;/strong&gt; 模式下（使用 vim 默认设置而不是 vi 的）。（搜索 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h --noplugin&lt;/code&gt; 命令了解更多启动加载方式）

如果仍旧能够出现该错误，那么这极有可能是 vim 本身的 bug，请给 &lt;a href=&quot;&amp;quot;https://groups.google.com/forum/#!forum/vim_dev&amp;quot;&quot;&gt;vim_dev&lt;/a&gt; 发送邮件反馈错误，多数情况下问题不会立刻解决，你还需要进一步研究

许多插件经常会提供新的（默认的/自动的）操作。如果在保存的时候发生了，那么请用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:verb au BufWritePost&lt;/code&gt; 命令检查潜在的问题

如果你在使用一个插件管理工具，将插件行注释调，再进行调试。

问题还没有解决？如果不是插件的问题，那么肯定是你的自定义的设置的问题，可能是你的 options 或 autocmd 等等。

到了一行行代码检查的时候了，不断地排除缩小检查范围知道你找出错误，根据二分法的原理你不会花费太多时间的。

在实践过程中，可能就是这样，把 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:finish&lt;/code&gt; 放在你的 &lt;strong&gt;vimrc&lt;/strong&gt; 文件中间，Vim 会跳过它之后的设置。如果问题还在，那么问题就出在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:finish&lt;/code&gt;之前的设置中，再把&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:finish&lt;/code&gt;放到前一部分设置的中间位置。否则问题就出现在它后面的半部分设置，那么就把&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:finish&lt;/code&gt;放到后半部分的中间位置。不断的重复即可找到。

&lt;h3 id=&quot;调整日志等级&quot;&gt;调整日志等级&lt;/h3&gt;

Vim 现在正在使用的另一个比较有用的方法是增加 debug 信息输出详细等级。现在 Vim 支持 9 个等级，可以用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;verbose&apos;&lt;/code&gt;命令查看。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/tmp/&lt;/span&gt;foo
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;verbose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;w&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;verbose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这可以显示出所有引用的文件、没有变化的文件或者各种各样的作用于保存的插件。

如果你只是想用简单的命令来提高等级，也是用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:verbose&lt;/code&gt; ，放在其他命令之前，通过计数来指明等级，默认是 1.

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;verb&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;verbose&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot;  verbose=1&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;verb&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;verbose&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot;  verbose=10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

通常用等级 1 来显示上次从哪里设置的选项

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;verb&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ai&lt;/span&gt;?
&lt;span class=&quot;c&quot;&gt;&quot;      Last set from ~/.vim/vimrc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

一般等级越高输出信息月详细。但是不要害怕，亦可以把输出导入到文件中：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;verbosefile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/tmp/&lt;/span&gt;foo &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;verbose&lt;/span&gt; echo &lt;span class=&quot;s2&quot;&gt;&quot;foo&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;vsplit&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/tmp/&lt;/span&gt;foo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

你可以一开始的时候就打开 verbosity，用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-V&lt;/code&gt; 选项，它默认设置调试等级为 10。 例如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim -V5&lt;/code&gt;

&lt;h3 id=&quot;查看启动日志&quot;&gt;查看启动日志&lt;/h3&gt;

&lt;h3 id=&quot;查看运行时日志&quot;&gt;查看运行时日志&lt;/h3&gt;

&lt;h3 id=&quot;vim-脚本调试&quot;&gt;Vim 脚本调试&lt;/h3&gt;

如果你以前使用过命令行调试器的话，对于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:debug&lt;/code&gt;命令你很快就会感到熟悉。

只需要在任何其他命令之前加上&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:debug&lt;/code&gt;就会让你进入调试模式。也就是，被调试的 Vim 脚本会在第一行停止运行，同时该行会被显示出来。

想了解可用的 6 个调试命令，可以查阅&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &amp;gt;cont&lt;/code&gt;和阅读下面内容。需要指出的是，类似 gdb 和其他相似调试器，调试命令可以使用它们的简短形式：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt;、 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;q&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt;、 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt;。

除了上面的之外，你还可以自由地使用任何 Vim 的命令。比如，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:echo myvar&lt;/code&gt;，该命令会在当前的脚本代码位置和上下文上被执行。

只需要简单使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:debug 1&lt;/code&gt;，你就获得了&lt;a href=&quot;https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop&quot;&gt;REPL&lt;/a&gt;调试特性。

当然，调试模式下是可以定义断点的，不然的话每一行都去单步调试就会十分痛苦。（断点之所以被叫做断点，是因为运行到它们的时候，运行就会停止下来。因此，你可以利用断点跳过自己不感兴趣的代码区域）。请查阅&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :breakadd&lt;/code&gt;、 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :breakdel&lt;/code&gt;和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :breaklist&lt;/code&gt;获取更多细节。

假设你需要知道你每次在保存一个文件的时候有哪些代码在运行：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;au&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;BufWritePost&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; signify  BufWritePost&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot;     *         call sy#start()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;breakadd&lt;/span&gt; func *start
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;w&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; Breakpoint in &quot;sy#start&quot; line 1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; Entering Debug mode.  Type &quot;cont&quot; to continue.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; function sy#start&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; line 1: if g:signify_locked&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;s
&lt;span class=&quot;c&quot;&gt;&quot; function sy#start&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; line 3: endif&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; function sy#start&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; line 5: let sy_path = resolve(expand(&apos;%:p&apos;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;q&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;breakdel&lt;/span&gt; *
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

正如你所见，使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;cr&amp;gt;&lt;/code&gt;命令会重复之前的调试命令，也就是在该例子中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt;命令。

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:debug&lt;/code&gt;命令可以和&lt;a href=&quot;#verbosity&quot;&gt;verbose&lt;/a&gt;选项一起使用。

&lt;h3 id=&quot;语法文件调试&quot;&gt;语法文件调试&lt;/h3&gt;

语法文件由于包含错误的或者复制的正则表达式，常常会使得 Vim 的运行较慢。如果 Vim 在编译的时候包含了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+profile&lt;/code&gt; &lt;a href=&quot;#what-kind-of-vim-am-i-running&quot;&gt;feature&lt;/a&gt;特性，就可以给用户提供一个超级好用的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:syntime&lt;/code&gt;命令。

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;syntime&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;on&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; 多次敲击&amp;lt;c-l&amp;gt;来重绘窗口，这样的话就会使得相应的语法规则被重新应用一次&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;syntime&lt;/span&gt; off
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;syntime&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;report&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

输出结果包含了很多的度量维度。比如，你可以通过结果知道哪些正则表达式耗时太久需要被优化；哪些正则表达式一直在别使用但重来没有一次成功匹配。

请查阅&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h :syntime&lt;/code&gt;。

&lt;h2 id=&quot;杂项&quot;&gt;杂项&lt;/h2&gt;

&lt;h3 id=&quot;附加资源&quot;&gt;附加资源&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;资源名称&lt;/th&gt;
      &lt;th&gt;简介&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;http://www.moolenaar.net/habits.html&quot;&gt;七个高效的文本编辑习惯&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;作者：Bram Moolenaar（即 Vim 的作者）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;http://www.moolenaar.net/habits_2007.pdf&quot;&gt;七个高效的文本编辑习惯 2.0（PDF 版）&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;同上&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/views/linux/libraryview.jsp?sort_order=asc&amp;amp;sort_by=Title&amp;amp;search_by=scripting+the+vim+editor&quot;&gt;IBM DeveloperWorks: 使用脚本编写 Vim 编辑器&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Vim 脚本编写五辑&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;http://learnvimscriptthehardway.stevelosh.com&quot;&gt;《漫漫 Vim 路》&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;使用魔抓定制 Vim 插件&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;http://www.amazon.com/Practical-Vim-Edit-Speed-Thought/dp/1680501275/&quot;&gt;《 Vim 实践 (第 2 版)》&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;轻取 Vim 最佳书籍&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;http://vimcasts.org/episodes/archive&quot;&gt;Vimcasts.org&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Vim 录屏演示&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;http://www.viemu.com/a-why-vi-vim.html&quot;&gt;为什么是个脚本都用 vi？&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;常见误区释疑&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;http://stackoverflow.com/a/1220118&quot;&gt;你不爱 vi，所以你不懂 Vim &lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;简明,扼要,准确的干货&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;vim-配置集合&quot;&gt;Vim 配置集合&lt;/h3&gt;

目前，网上有很多流行 Vim 配置集合，对于 Vim 配置集合，个人认为有利有弊。
对于维护的比较好的配置，比如 &lt;a href=&quot;http://spacevim.org/cn/&quot;&gt;SpaceVim&lt;/a&gt; 还是值得尝试的，可以节省很多自行配置的时间。
当然，网上还有很多其他很流行的配置，比如：

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/wklken/k-vim&quot;&gt;k-vim&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/amix/vimrc&quot;&gt;amix’s vimrc&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/carlhuda/janus&quot;&gt;janus&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;常见问题&quot;&gt;常见问题&lt;/h3&gt;

&lt;h4 id=&quot;编辑小文件时很慢&quot;&gt;编辑小文件时很慢&lt;/h4&gt;

有两个因素对性能影响非常大：

&lt;ol&gt;
  &lt;li&gt;
    过于复杂的 &lt;strong&gt;正则表达式&lt;/strong&gt; 。尤其是 Ruby 的语法文件，以前会造成性能下降。（见&lt;a href=&quot;#debugging-syntax-files&quot;&gt;调试语法文件&lt;/a&gt;）
  &lt;/li&gt;
  &lt;li&gt;
    &lt;strong&gt;屏幕重绘&lt;/strong&gt; 。有一些功能会强制重绘所有行。
  &lt;/li&gt;
&lt;/ol&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;典型肇事者&lt;/th&gt;
      &lt;th&gt;原因&lt;/th&gt;
      &lt;th&gt;解决方案&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set cursorline&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;会导致所有行重绘&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set nocursorline&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set cursorcolumn&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;会导致所有行重绘&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set nocursorcolumn&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set relativenumber&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;会导致所有行重绘&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set norelativenumber&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set foldmethod=syntax&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;如果语法文件已经很慢了，这只会变得更慢&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set foldmethod=manual&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set foldmethod=marker&lt;/code&gt; 或者使用&lt;a href=&quot;https://github.com/Konfekt/FastFold&quot;&gt;快速折叠&lt;/a&gt;插件&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set synmaxcol=3000&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;由于内部表示法，Vim 处理比较长的行时会有问题。让它高亮到 3000 列……&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set synmaxcol=200&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;matchparen.vim&lt;/td&gt;
      &lt;td&gt;Vim 默认加载的插件，用正则表达式查找配对的括号&lt;/td&gt;
      &lt;td&gt;禁用插件：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h matchparen&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;strong&gt;注意&lt;/strong&gt;：只有在你真正遇到性能问题的时候才需要做上面的调整。在大多数情况下使用上面提到的选项是完全没有问题的。

&lt;h4 id=&quot;编辑大文件的时候很慢&quot;&gt;编辑大文件的时候很慢&lt;/h4&gt;

Vim 处理大文件最大的问题就是它会一次性读取整个文件。这么做是由于缓冲区的内部机理导致的（在 &lt;a href=&quot;https://groups.google.com/forum/#!topic/vim_dev/oY3i8rqYGD4/discussion&quot;&gt;vim_dev&lt;/a&gt; 中讨论）。

如果只是想查看的话，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tail hugefile | vim -&lt;/code&gt; 是一个不错的选择。

如果你能接受没有语法高亮，并且禁用所有插件和设置的话，使用：

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vim &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; NONE &lt;span class=&quot;nt&quot;&gt;-N&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这将会使得跳转变快很多，尤其是省去了基于很耗费资源的正则表达式的语法高亮。你还可以告诉 Vim 不要使用交换文件和 viminfo 文件，以避免由于写这些文件而造成的延时：

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vim &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; NONE &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; NONE &lt;span class=&quot;nt&quot;&gt;-N&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

简而言之，尽量避免使用 Vim 写过大的文件。

&lt;h4 id=&quot;持续粘贴为什么我每次都要设置-paste-模式&quot;&gt;持续粘贴（为什么我每次都要设置 ‘paste’ 模式）&lt;/h4&gt;

持续粘贴模式让终端模拟器可以区分输入内容与粘贴内容。

你有没有遇到过往 Vim 里粘贴代码之后被搞的一团糟？

这在你使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmd+v&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shirt-insert&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;middle-click&lt;/code&gt; 等进行粘贴的时候才会发生。
因为那样的话你只是向终端模拟器扔了一大堆的文本。
Vim 并不知道你刚刚是粘贴的文本，它以为你在飞速的输入。
于是它想缩进这些行但是失败了。

这明显不是个问题，如果你用 Vim 的寄存器粘贴，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;+p&lt;/code&gt; ，这时 Vim 就知道了你在粘贴，就不会导致格式错乱了。

使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set paste&lt;/code&gt; 就可以解决这个问题正常进行粘贴。见 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;paste&apos;&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h &apos;pastetoggle&apos;&lt;/code&gt; 获取更多信息。

如果你受够了每次都要设置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;paste&apos;&lt;/code&gt; 的话，看看这个能帮你自动设置的插件：&lt;a href=&quot;https://github.com/ConradIrwin/vim-bracketed-paste&quot;&gt;bracketed-paste&lt;/a&gt;。

&lt;a href=&quot;http://cirw.in/blog/bracketed-paste&quot;&gt;点此&lt;/a&gt;查看该作者对于这个插件的更多描述。

Neovim 尝试把这些变得更顺畅，如果终端支持的话，它会自动开启持续粘贴模式，无须再手动进行切换。

&lt;h4 id=&quot;在终端中按-esc-后有延时&quot;&gt;在终端中按 ESC 后有延时&lt;/h4&gt;

如果你经常使用命令行，那么肯定要接触 &lt;em&gt;终端模拟器&lt;/em&gt; ，如 xterm、gnome-terminal、iTerm2 等等（与实际的&lt;a href=&quot;https://en.wikipedia.org/wiki/Computer_terminal&quot;&gt;终端&lt;/a&gt;不同）。

终端模拟器与他们的祖辈一样，使用 &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97&quot;&gt;转义序列&lt;/a&gt; （也叫 &lt;em&gt;控制序列&lt;/em&gt; ）来控制光标移动、改变文本颜色等。转义序列就是以转义字符开头的 ASCII 字符串（用&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E8%84%B1%E5%AD%97%E7%AC%A6%E8%A1%A8%E7%A4%BA%E6%B3%95&quot;&gt;脱字符表示法&lt;/a&gt;表示成 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^[&lt;/code&gt; ）。当遇到这样的字符串后，终端模拟器会从&lt;a href=&quot;https://en.wikipedia.org/wiki/Terminfo&quot;&gt;终端信息&lt;/a&gt;数据库中查找对应的动作。

为了使用问题更加清晰，我会先来解释一下什么是映射超时。在映射存在歧义的时候就会产生映射超时：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;nnoremap &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;echo &lt;span class=&quot;s1&quot;&gt;&apos;foo&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;nnoremap &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ab&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;echo &lt;span class=&quot;s1&quot;&gt;&apos;bar&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上面的例子中两个映射都能正常工作，但是当输入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;,a&lt;/code&gt; 之后，Vim 会延时 1 秒，因为它要确认用户是否还要输入那个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;。

转义序列会产生同样的问题：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;esc&amp;gt;&lt;/code&gt; 作为返回普通模式或取消某个动作的按键而被大量使用&lt;/li&gt;
  &lt;li&gt;光标键使用转义序列进行的编码&lt;/li&gt;
  &lt;li&gt;Vim 期望 &lt;kbd&gt;Alt&lt;/kbd&gt; （也叫作 &lt;em&gt;Mate Key&lt;/em&gt; ）会发送一个正确的 8-bit 编码的高位，但是许多终端模拟器并不支持这个（也可能默认没有启用），而只是发送一个转义序列作为代替。&lt;/li&gt;
&lt;/ul&gt;

你可以这样测试上面所提到的事情： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim -u NONE -N&lt;/code&gt; 然后输入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&amp;lt;c-v&amp;gt;&amp;lt;left&amp;gt;&lt;/code&gt; ，你会看到一个以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^[&lt;/code&gt; 开头的字符串，表明这是一个转义序列，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^[&lt;/code&gt; 就是转义字符。

简而言之，Vim 在区分录入的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;esc&amp;gt;&lt;/code&gt; 和转义序列的时候需要一定的时间。

默认情况下，Vim 用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:set timeout timeoutlen=1000&lt;/code&gt;，就是说它会用 1 秒的时间来区分有歧义的映射 &lt;em&gt;以及&lt;/em&gt; 按键编码。这对于映射来说是一个比较合理的值，但是你可以自行定义按键延时的长短，这是解决该问题最根本的办法：

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;timeout&lt;/span&gt;           &quot; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; mappings
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;timeoutlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1000&lt;/span&gt;   &quot; default value
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ttimeout&lt;/span&gt;          &quot; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;key&lt;/span&gt; codes
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ttimeoutlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;    &quot; unnoticeable small value
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h ttimeout&lt;/code&gt; 里你可以找到一个关于这些选项之间关系的小表格。

而如果你在 tmux 中使用 Vim 的话，别忘了把下面的配置加入到你的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.tmux.conf&lt;/code&gt;文件中：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;set -sg escape-time 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;无法重复函数中执行的搜索&quot;&gt;无法重复函数中执行的搜索&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;在命令中的搜索（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:substitute&lt;/code&gt; 等）内容会改变“上次使用的搜索内容”。（它保存在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;寄存器中，用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:echo @/&lt;/code&gt; 可以输出它里面的内容）&lt;/li&gt;
  &lt;li&gt;简单的文本变化可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt; 重做。（它保存在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt; 寄存器，用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:echo @.&lt;/code&gt; 可以输出它的内容）&lt;/li&gt;
&lt;/ul&gt;

而在你在函数中进行这些操作的时候，一切就会变得不同。因此你不能用 N/n 查找某个函数刚刚查找的内容，也不能重做函数中对文本的修改。

帮助文档：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h function-search-undo&lt;/code&gt;。
</description>
        <pubDate>Mon, 27 Mar 2017 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/vim-galore-zh-cn/</link>
        <guid isPermaLink="true">https://wsdjeg.net/vim-galore-zh-cn/</guid>
        
        <category>neovim</category>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>SpaceVim 第一个版本</title>
        <description>
&lt;blockquote&gt;
  Like spacemacs, but for vim.
&lt;/blockquote&gt;

SpaceVim 放在 github 上， 3 天获取 700+ 星，该项目不仅适合 vim 以及 neovim 老用户，
对于新用户来说，也是非常适合的。

@Shougo 大神 以及 @mhinz 大神对此项目也很支持，
另外，该项目在 Hacker News 首页也出现过。拥有 200+ points 。

在 gittter #neovim 内， 也有用户支持该项目。

目前该项目 80% 收藏者来自国外，国内确实没有找到很好的 post 平台，
现尝试在 V2EX 上发布下， 希望有更多的 vim 用户支持，让 vim 中文社区更加活跃。

该项目地址 github 地址是 ： SpaceVim/SpaceVim

官网 ： http://spacevim.org

SpaceVim 是高度可定制的模块化 Vim 配置集合，适合开发各种语言，
尤其是 Java c c++ python php 等常用语言，并且拥有非常优秀的 UI 界面，
用户可以根据自己需求载入需要的模块。如果有兴趣，欢迎进群大家一起讨论。
本群为非常专业的技术讨论群，请勿水！

</description>
        <pubDate>Wed, 18 Jan 2017 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/first-release-of-spacevim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/first-release-of-spacevim/</guid>
        
        <category>vim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>在 Vim 中使用聊天工具</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#安装&quot; id=&quot;markdown-toc-安装&quot;&gt;安装&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#微信及qq聊天&quot; id=&quot;markdown-toc-微信及qq聊天&quot;&gt;微信及QQ聊天&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#依赖&quot; id=&quot;markdown-toc-依赖&quot;&gt;依赖&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#启动&quot; id=&quot;markdown-toc-启动&quot;&gt;启动&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

在装了 arch 之后，没有庄 gnome 等桌面，而是采用了 I3-WM 这样的平铺桌面，
平时有聊天的需求，又无法忍受手机打字那么麻烦，
于是做了一个 Linux 系统下 借助 Vim 的聊天工具。分享给大家：

&lt;h2 id=&quot;安装&quot;&gt;安装&lt;/h2&gt;

&lt;div class=&quot;language-viml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; dein#&lt;span class=&quot;nb&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;wsdjeg/vim-chat&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

安装完成之后，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;call chat#chatting#OpenMsgWin()&lt;/code&gt;，打开聊天窗口。

&lt;h2 id=&quot;微信及qq聊天&quot;&gt;微信及QQ聊天&lt;/h2&gt;

&lt;h3 id=&quot;依赖&quot;&gt;依赖&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/sjdy521/Mojo-Webqq&quot;&gt;mojo-webqq&lt;/a&gt; 和 &lt;a href=&quot;https://github.com/sjdy521/Mojo-Weixin&quot;&gt;mojo-weixin&lt;/a&gt;：用于将QQ及微信协议转换成irc协议&lt;/li&gt;
  &lt;li&gt;IRC 依赖模块: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cpanm -v Mojo::IRC::Server::Chinese&lt;/code&gt;, 详见： &lt;a href=&quot;https://github.com/sjdy521/Mojo-Webqq/blob/master/IRC.md&quot;&gt;irc.md&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://irssi.org/&quot;&gt;irssi&lt;/a&gt;: irc 聊天客户端&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://feh.finalrewind.org/&quot;&gt;feh&lt;/a&gt;: 图片查看器，用于打开二维码&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/neovim/neovim&quot;&gt;neovim&lt;/a&gt;： vim8 的异步存在&lt;a href=&quot;https://github.com/vim/vim/issues/1198&quot;&gt;问题&lt;/a&gt;，无法实现相应功能，故只能在neovim下使用&lt;/li&gt;
  &lt;li&gt;Linux: 目前仅在Linux下测试成功， Windows 下请直接使用QQ客户端&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;启动&quot;&gt;启动&lt;/h3&gt;

首先启动 QQ 服务器 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;call chat#qq#start()&lt;/code&gt;, 然后会自动弹出一个二维码，手机扫描下就可以登录了。neovim 默认使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt + x&lt;/code&gt; 打开/关闭聊天窗口。

</description>
        <pubDate>Fri, 30 Dec 2016 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/chatting-in-vim/</link>
        <guid isPermaLink="true">https://wsdjeg.net/chatting-in-vim/</guid>
        
        <category>vim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>为什么要写博客</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#为什么要写博客&quot; id=&quot;markdown-toc-为什么要写博客&quot;&gt;为什么要写博客&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#为什么使用独立站点&quot; id=&quot;markdown-toc-为什么使用独立站点&quot;&gt;为什么使用独立站点&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#为什么使用邮件评论&quot; id=&quot;markdown-toc-为什么使用邮件评论&quot;&gt;为什么使用邮件评论&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#关于社交软件&quot; id=&quot;markdown-toc-关于社交软件&quot;&gt;关于社交软件&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;h2 id=&quot;为什么要写博客&quot;&gt;为什么要写博客&lt;/h2&gt;

其实关于这个问题，至今我也没有完全想明白。可能是因为上了年纪的原因，有些怀旧，但是发现过往的记忆似乎很难完全想起来了。
因此，我觉得有必要日常做一些简单的记录。

&lt;ol&gt;
  &lt;li&gt;我想记录一些值得记忆的人和事，也许多年以后回来看看，会很欣慰&lt;/li&gt;
  &lt;li&gt;记录日常遇到的一些问题及解决的方法&lt;/li&gt;
  &lt;li&gt;记录折腾一些有意思的小玩意的过程&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;为什么使用独立站点&quot;&gt;为什么使用独立站点&lt;/h2&gt;

其实早在 2004 年 QQ 出现的时候，就开始写 QQ 空间日志，再到后来的新浪博客、网易博客、百度空间、博客园、CSDN 等等，
这些平台都有使用过。但是都存在各种各样的问题，包括：

&lt;ol&gt;
  &lt;li&gt;页面样式定制不自由，个人网站每一个字符、每一张图片、每一个链接都应该是完全可控的。&lt;/li&gt;
  &lt;li&gt;跑路风险，备份麻烦。这些平台都有停止服务的可能，那些写在其上的文字很难备份转移。&lt;/li&gt;
  &lt;li&gt;广告满天飞，尤其是 CSDN。&lt;/li&gt;
  &lt;li&gt;登录才能阅读，像知乎、CSDN 这类网站，非登录用户都无法阅读全文。&lt;/li&gt;
&lt;/ol&gt;

独立站点的优势在于：

&lt;ol&gt;
  &lt;li&gt;完全可控，自己个人站点中每一个字符、每一张图片、每一个链接都是可控的&lt;/li&gt;
  &lt;li&gt;使用 Git 仓库，编辑历史可以追溯，备份也方便&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;为什么使用邮件评论&quot;&gt;为什么使用邮件评论&lt;/h2&gt;

邮件更加私密，也显得更加正式。同时，也可以避免广告、spam 等内容直接在评论区显示。

&lt;h2 id=&quot;关于社交软件&quot;&gt;关于社交软件&lt;/h2&gt;

之前用过的社交平台软件，各种各样问题都有。以至于有很长一段时间，很想彻底摆脱这些社交软件。

Reddit 账号已删除，留张图片纪念一下：

&lt;img src=&quot;../images/old-reddit.png&quot; alt=&quot;&quot; /&gt;
</description>
        <pubDate>Wed, 24 Jun 2015 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/20150624/</link>
        <guid isPermaLink="true">https://wsdjeg.net/20150624/</guid>
        
        <category>blog</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>可爱的小天使</title>
        <description>
这是一个值得记忆的日子，今天我们家迎来了一位新的小生命。因为自己的工作原因，在老婆最辛苦的这段日子里，
没能够时常陪伴身边。

&lt;style&gt;
  .image-gallery {
    overflow: auto;
    margin-left: -1% !important;
  }
  .image-gallery li {
    float: left;
    display: block;
    padding:3px 3px;
    width: 19%;
  }
  .image-gallery li a {
    text-align: center;
    text-decoration: none !important;
    color: #777;
  }
  .image-gallery li a span {
    display: block;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    padding: 3px 0;
  }
  .image-gallery li a img {
    width: 100%;
    display: block;
  }
&lt;/style&gt;

&lt;ul class=&quot;image-gallery&quot;&gt;
  
&lt;/ul&gt;

</description>
        <pubDate>Mon, 25 May 2015 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/my-little-daughter/</link>
        <guid isPermaLink="true">https://wsdjeg.net/my-little-daughter/</guid>
        
        <category>love</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>不忘初心、方得始终</title>
        <description>《华严经》里说：“不忘初心，方得始终。”

记得很长时段时间，签名是：感叹那两个少年，一个温柔了岁月，一个经验了流年。
已经无从考证这句话到底来自哪里了。当时第一次看到这段话就觉得深受感触。

每个人，在最初的时候可能会有各种各样的梦想。但是随着时间的推移，生活的磨砺。
会让我们越来越执着于眼前，淡忘了曾经的梦想。梦想是每个人出发的起点，不忘初心，
才会让自己明确从哪里来，到哪里去。

初心，给人强大的勇气，把一切困难都踩在脚下。人生最大的困厄，就是被人驱使。
被父母催促着去上学，被领导吩咐着去做事，被生活逼迫着去赚钱。
看似是出于无奈，实则缺少了情愿，总像背负着巨石，压得喘不过气来。
转换一下思维，调整一下状态，从自己的初心开始，想自己想做的事，
想着自己该肩负的责任，不后悔，肯坚持，虽难免生长的阵痛，却会得到成长的快乐。

初心，给了人积极进取的人生状态，随时能回到最初的原点，重新开始。
人生的经历，在我们大脑里塞满了各种各样的东西。
有时我们满足于鲜花和掌声，喜欢在美好的过去里追忆；
有时我们则沉浸于挫折的苦痛，在灰暗的心空里踽踽独行。
其实我们最需要的，就是不忘初心，倾空自己，回到充满渴望的婴儿般的状态，
永远在拼命地汲取，永远在奋力前行的路上。

在这个时代，初心常常被我们遗忘，正如纪伯伦所说：“我们已经走的太远，以至于忘记了为什么出发。”
人生只有一次，生命无法重来，要记得自己的初心。
经常回头望一下自己的来路，回忆起当初为什么起程；
经常让自己回到起点，给自己鼓足从头开始的勇气；
经常纯净自己的内心，给自己一双澄澈的眼睛，
不忘初心，才会找对人生的方向，才会坚定我们的追求，
抵达自己的初衷，也更容易抵达人生的目的地。
</description>
        <pubDate>Sat, 12 Jul 2014 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/never-forget-the-beginning/</link>
        <guid isPermaLink="true">https://wsdjeg.net/never-forget-the-beginning/</guid>
        
        <category>love</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>强大的vim命令 :g 和 :s</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#命令形式&quot; id=&quot;markdown-toc-命令形式&quot;&gt;命令形式&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#global与substitute&quot; id=&quot;markdown-toc-global与substitute&quot;&gt;global与substitute&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#global标志的range用法&quot; id=&quot;markdown-toc-global标志的range用法&quot;&gt;global标志的[range]用法&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:global&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:substitute&lt;/code&gt; 命令是 Vim 最强大的命令之一，
将其摸透用熟可以事半功倍，在这里我总结了一些网上的网上的经典问题，
结合自己的使用和理解，通过实例详细介绍一下其用法。示例难度不一，
其中有些可能并没有多少实用性，仅仅是为了展示功能。

&lt;h2 id=&quot;命令形式&quot;&gt;命令形式&lt;/h2&gt;

阅读 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:help :g&lt;/code&gt;可知，该命令的使用形式为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:[range]global/{pattern}/{command}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt; 命令在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt; 指定的文本范围内（缺省为整个文件）查找 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{pattern}&lt;/code&gt;，
然后对匹配到的行执行命令&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{command}&lt;/code&gt;，如果希望对没匹配上的行执行命令，
则使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global!&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vglobal&lt;/code&gt; 命令。

先来看 Vim 用户手册里的一个经典例子。

&lt;strong&gt;【例1】倒序文件行（即unix下的tac命令）&lt;/strong&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:g/^/m 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这条命令用行首标记 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^&lt;/code&gt; 匹配文件的所有行（这是查找的一个常用技巧，如果用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt;则是匹配非空行，不满足本例要求），
然后用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;move&lt;/code&gt; 命令依次将每行移到第一行（第0行的下一行），从而实现了倒序功能。

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt;命令实际上是分成两步执行：首先扫描&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt;指定范围内的所有行，
给匹配&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{pattern}&lt;/code&gt;的行打上标记；然后依次对打有标记的行执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{command}&lt;/code&gt;命令，
如果被标记的行在对之前匹配行的命令操作中被删除、移动或合并，则其标记自动消失，而不对该行执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{command}&lt;/code&gt;命令。
标记的概念很重要，以例说明。

&lt;strong&gt;【例2】删除偶数行&lt;/strong&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:g/^/+1 d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这条命令也是匹配所有行，然后隔行删除（其中+1用以定位于当前行的下一行）。
为什么是隔行呢？因为在对第一行执行+1 d命令时删除的是第二行，而第二行虽然也被标记了，但已不存在了，
因此不会执行删除第三行的命令。

本例也可以用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:normal&lt;/code&gt;命令实现：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:%normal! jdd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt; 指定整个文件，然后依次执行普通模式下的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jdd&lt;/code&gt;，即下移删除一行。与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt; 命令不同之处在于，
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%normal! jdd&lt;/code&gt; 是按照行号顺序执行，在第一行时删除了第二行，后面的所有行号都减一，
因此在第二行执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jdd&lt;/code&gt; 时删除的是原来的第四行。也就是说，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt; 命令是通过偶数行标记的消失实现的，
而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;normal&lt;/code&gt; 命令是通过后续行的自动前移实现的。

&lt;strong&gt;【例3】删除奇数行&lt;/strong&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:g/^/d|m.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

光是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:g/^/d&lt;/code&gt;显然不行，这会删除所有行，我们需要用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;move&lt;/code&gt;命令把偶数行的标记去掉。当然，本例可以很简单的转换成【例2】，在此只是用来强调标记的概念。

本例若想用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;normal&lt;/code&gt; 命令实现比较有意思，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%normal! dd&lt;/code&gt;也同样会删除整个文件，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%normal! jkdd&lt;/code&gt;就可以，我不知道两者为什么不同，可能和normal命令内部的运行机制有关。

&lt;h2 id=&quot;global与substitute&quot;&gt;global与substitute&lt;/h2&gt;

不少人觉得这两个命令差不多，的确，它们的形式很相似，都是要进行查找匹配，
只不过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:substitute&lt;/code&gt; 执行的是替换而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:global&lt;/code&gt; 执行的其它命令（当然，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;substitute&lt;/code&gt; 缺省的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt; 是当前行，这点也不同）。
先看两个例子，体会一下&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:s&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:g&lt;/code&gt;不同的思维方式。

&lt;strong&gt;【例4】double所有行&lt;/strong&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:%s/.*/&amp;amp;\r&amp;amp;/
:g/^/t.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;substitue&lt;/code&gt;是查找任意行，然后替换为两行夹回车；&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt;是将每一行复制（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:t&lt;/code&gt;就是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:copy&lt;/code&gt;）到自己下面，更加清晰明了。

&lt;strong&gt;【例5】把以回车排版、以空行分段的文本变成以回车分段的文本&lt;/strong&gt;

很多txt格式的ebook，以及像vim help这样的文本，每行的字符数受限，段之间用空行分隔。若把它们拷贝到word里，那些硬回车和空行就比较讨厌了，虽然word里也有自动调整格式的功能，不过在Vim里搞定更是小菜一碟。先看看用替换如何实现。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:%s/\n\n\@!//
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\n\n\@!&lt;/code&gt;是查找后面不跟回车的回车（关于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\@!&lt;/code&gt;的用法请&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:h /\@!&lt;/code&gt;，在此不多说了），然后替换为空，也就是去掉用于排版的回车。

注：如果等宽段之间无空行，则合并命令变为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:%s/\n\%(\s\{2,}\|\n\)\@!//g&lt;/code&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt;命令则完全是另一种思路。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:g/./,/^$/j
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/./&lt;/code&gt;标记非空行，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/^$/&lt;/code&gt;查找其后的空行，然后对二者之间的行进行合并操作。也许有人会问，段中的每一行会不会都执行了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j&lt;/code&gt;命令？前面已经说过，在之前操作中消失掉的标记行不执行操作命令，在处理每段第一行时已经把段内的其余行都合并了，所以每段只会执行一次&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j&lt;/code&gt;命令。这条命令使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt;标记做为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt;的起始行，这样的用法后面还会详述。

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt;经常与&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;substitute&lt;/code&gt;组合使用，用前者定位满足一定条件的行，用后者在这些行中进行查找替换。如：

【例6】将aaa替换成bbb，除非该行中有ccc或者ddd

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:v/ccc\|ddd/s/aaa/bbb/g
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;strong&gt;【例7】将aaa替换成bbb，条件是该行中有ccc但不能有ddd&lt;/strong&gt;

如何写出一个匹配aaa并满足行内有ccc但不能有ddd的正则表达式？我不知道。即便能写出来，也必定极其复杂。用global命令则并不困难：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:g/ccc/if getline(&apos;.&apos;) !~ &apos;ddd&apos; | s/aaa/bbb/g
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

该命令首先标记匹配&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ccc&lt;/code&gt;的行，然后执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt;命令（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt;也是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ex&lt;/code&gt;命令！），&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getline&lt;/code&gt;函数取得当前行，然后判断是否匹配&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ddd&lt;/code&gt;，如果不匹配（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!~&lt;/code&gt;的求值为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;）则执行替换。要掌握这样的用法需要对&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ex&lt;/code&gt;命令、Vim函数和表达式有一定了解才行，实际上，这条命令已经是一个快捷版的脚本了。可能有人会想，把&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v&lt;/code&gt;连起来用不就行了么，可惜&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt;命令不支持（恐怕也没法支持）嵌套。

&lt;h2 id=&quot;global标志的range用法&quot;&gt;global标志的[range]用法&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:h range
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt;命令第一步中所设的标记，可以被用来为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{command}&lt;/code&gt;命令设定各种形式的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt;。在【例2】和【例5】中都已使用了这一技巧，灵活使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt;，是一项重要的基本功。先看看【例2】和【例3】的一般化问题。

&lt;strong&gt;【例8】每n行中，删除前/后m行（例如，每10行删除前/后3行）&lt;/strong&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:g/^/,+2 d | ,+6 m -1
:g/^/,+6 m -1 | +1,+3 d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这两个命令还是利用move来清除保留行的标志，需要注意的是执行第二个命令时的当前行是第一个命令寻址并执行后的位置。再看两个更实用点的例子。

&lt;blockquote&gt;
  感谢 gqqnb2005 提醒，C++ preprocessor 已經是個很複雜很强大的語言了，下面的两个示例仅供参考理解 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:g&lt;/code&gt; 命令配合 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; 命令搜索确定 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;range&lt;/code&gt;,
实际上，语法级别的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;range&lt;/code&gt; 确定，使用正则表达式是完全不够的。
&lt;/blockquote&gt;

&lt;strong&gt;【例9】提取条件编译内容。例如，在一个多平台的C程序里有大量的条件编译代码：&lt;/strong&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#ifdef WIN32
XXX1
XXX2
#endif
...
#ifdef WIN32
XXX3
XXX4
#else
YYY1
YYY2
#endif
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

现在用global命令把Win32平台下代码提取出来，拷贝到文件末：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:g/#ifdef WIN32/+1,/#else\|#endif/-1 t $
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t&lt;/code&gt;命令的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt;是由逗号分隔，起始行是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/#ifdef WIN32/&lt;/code&gt;标记行的下一行，结束行是一个查找定位，是在起始行后面出现的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#endif&lt;/code&gt;或&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#else&lt;/code&gt;的上一行，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t&lt;/code&gt;将二者间的内容复制到末尾。

&lt;strong&gt;【例10】提取上述C程序中的非Win32平台的代码（YYY部分）&lt;/strong&gt;

首先说明一下，这个例子比前例要复杂的多，主要涉及的是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt;的操作，已经和global命令没多少关系，大可不看。加到这的目的是把问题说完，供喜欢细抠的朋友参考。本例的复杂性在于：首先，不能简单的用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#else&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#endif&lt;/code&gt;定位，因为代码中可能有其它的条件编译，我们必须要将查找范围限定在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#ifdef WIN32&lt;/code&gt;的block中；另外，在block中可能并没有&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#else&lt;/code&gt;部分，这会给定位带来很大麻烦。解决方法是：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:try | g/#ifdef WIN32//#else/+1, /#endif/-1 t $ | endtry
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

先不管try和endtry，只看中间的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt;部分：找到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WIN32&lt;/code&gt;，再向后找到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#else&lt;/code&gt;，将其下一行作为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt;的起始行，然后从当前的光标（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WIN32&lt;/code&gt;所在行，而非刚找到的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#else&lt;/code&gt;的下一行）向下找到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#endif&lt;/code&gt;，将其上一行作为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt;的结束行，然后执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t&lt;/code&gt;命令。但对于没有&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#else&lt;/code&gt;的block，如第一段代码，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt;的起始行是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YYY1&lt;/code&gt;，而结束行是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XXX2&lt;/code&gt;（因为查找&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#endif&lt;/code&gt;时是从第一行开始的，而不是从&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YYY1&lt;/code&gt;开始），这是一个非法的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt;，会引起exception，如果不放在try里面global命令就会立刻停止。

与逗号(,)不同，如果&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[range]&lt;/code&gt;是用分号(;)分隔的，则会使得当前光标移至起始行，在查找#endif时是从#else的下一行开始，这样就产生非法[range]，用不着try，但带来的问题是：没有#else的block会错误的把后面block中的#else部分找出来。
</description>
        <pubDate>Mon, 01 Jul 2013 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/vim-global-substitute/</link>
        <guid isPermaLink="true">https://wsdjeg.net/vim-global-substitute/</guid>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>欢迎来到 Racket</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#简介&quot; id=&quot;markdown-toc-简介&quot;&gt;简介&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#s-表达式&quot; id=&quot;markdown-toc-s-表达式&quot;&gt;S-表达式&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#高阶函数&quot; id=&quot;markdown-toc-高阶函数&quot;&gt;高阶函数&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#lambda-表达式&quot; id=&quot;markdown-toc-lambda-表达式&quot;&gt;Lambda 表达式&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#惰性求值&quot; id=&quot;markdown-toc-惰性求值&quot;&gt;惰性求值&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#闭包&quot; id=&quot;markdown-toc-闭包&quot;&gt;闭包&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#安装&quot; id=&quot;markdown-toc-安装&quot;&gt;安装&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#执行-racket-脚本&quot; id=&quot;markdown-toc-执行-racket-脚本&quot;&gt;执行 racket 脚本&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

Racket 是一种编程语言（programming language）—— Lisp 语言的一种方言和 Scheme 的一种派生语言；

&lt;h2 id=&quot;简介&quot;&gt;简介&lt;/h2&gt;

1958 年，人工智能之父 John McCarthy 发明了一种以 Lambda 演算为基础的符号处理语言，
1960 年 McCarthy 发表著名论文 Recursive Functions of Symbolic Expressions and Their Computation by Machine,
从此这种语言被命名为 LSIP (List Processor），其语法被命名为：符号表达式(S-Expression)。
LISP 构建在 7 个函数 [atom car cdr cond cons eq quote] 和 2 个特型 [lambda label] 之上。

Lisp诞生之初是为了纯粹的科学研究，代码执行像数学公式一样，以人的大脑来演算。
直到麦卡锡的学生斯蒂芬·罗素将eval函数在IBM 704机器上实现后，
才开启了Lisp作为一种计算机语言的历史。1962年，第一个完整的Lisp编译器在MIT诞生，
从此之后Lisp以MIT为中心向全世界传播。之后十多年，出现了各种Lisp方言。

1975年，Scheme诞生。Scheme同样诞生与MIT，它的设计哲学是最小极简主义，
它只提供必须的少数几个原语，所有其他的实用功能都由库来实现。在极简主义的设计思想下，
Scheme趋于极致的优雅，并作为计算机教学语言在教育界广泛使用。

1984年，Common Lisp诞生。在二十世纪七八十年代，由于Lisp方言过多，社区分裂，
不利于lisp整体的发展。从1981年开始，在一个Lisp黑客组织的运作下，
经过三年的努力整合后，于1984年推出了Common Lisp。由于Scheme的设计理念和其他Lisp版本不同，
所以尽管Common Lisp借鉴了Scheme的一些特点，但没有把Scheme整合进来。此后Lisp仅剩下两支方言： Common Lisp 和 Scheme。

从二十世纪九十年代开始，由于C++、Java、C#的兴起，Lisp逐渐没落。直到2005年后，
随着科学计算的升温，动态语言JavaScript、Python、Ruby的流行，Lisp又渐渐的回到人们的视线。
不过在Lisp的传统阵地教育界，Python作为强有力的挑战者对Scheme发起冲锋；
在2008年，MIT放弃了使用Scheme作为教学语言的SICP（计算机程序的构造和解释）课程，
而启用Python进行基础教学。同时美国东北大学另立炉灶，其主导的科学计算系统PLT Scheme开始迅猛发展；
2010年，PLT Scheme改名为Racket。近几年，The Racket Language连续成为年度最活跃语言网站，并驾齐驱的还有haskell网站。

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/62820991-907fce80-bb9f-11e9-9975-1cd92f9cfe79.jpg&quot; alt=&quot;lisp&quot; /&gt;

&lt;h2 id=&quot;s-表达式&quot;&gt;S-表达式&lt;/h2&gt;

首先说一下S-表达式：S-表达式的基本元素是list与atom。list由括号包围，
可包涵任何数量的由空格所分隔的元素，原子是其它内容。
其使用前缀表示法，在Lisp中既用作代码，也用作数据。如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1+2*3&lt;/code&gt;  写成前缀表达式就是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(+ 1 (* 2 3)) &lt;/code&gt;。

&lt;ul&gt;
  &lt;li&gt;优点：容易parse，简单纯粹，不用考虑什么优先级等，也是实现代码即数据的前提；&lt;/li&gt;
  &lt;li&gt;缺点：可读性不是很强；&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;高阶函数&quot;&gt;高阶函数&lt;/h2&gt;

高阶函数至少满足下列一个条件：

&lt;ul&gt;
  &lt;li&gt;接受一个或多个函数作为输入；&lt;/li&gt;
  &lt;li&gt;输出一个函数；&lt;/li&gt;
&lt;/ul&gt;

微积分中的导数就是一个例子，映射一个函数到另一个函数。在无类型 lambda 演算中，
所有函数都是高阶的。在函数式编程中，返回另一个函数的高阶函数被称为Curry化的函数。
Curry化即把接受多个参数的函数变换成接受一个单一参数（最初函数的第一个参数）的函数，
并且返回接受余下的参数而且返回结果的新函数的技术。如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f(x,y)=x+y&lt;/code&gt;, 如果给定了 y=1，则就得到了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g(x)=x+1&lt;/code&gt; 这个函数。

&lt;h2 id=&quot;lambda-表达式&quot;&gt;Lambda 表达式&lt;/h2&gt;

Racket中实用Lambda表达式来定义匿名函数，《如何设计程序》书中给出的使用原则是：
如果某个非递归函数只需要当参数使用一次，使用Lambda表达式。
如果想用Lambda表达式来表达递归，就需要引入Y组合子，Y 就是这样一个操作符，
它作用于任何一个 (接受一个函数作为参数的) 函数 F，就会返回一个函数 X。
再把 F 作用于这个函数 X，还是得到 X。所以 X 被叫做 F 的不动点(fixed point)，即 (Y F) = (F (Y F)) 。

&lt;h2 id=&quot;惰性求值&quot;&gt;惰性求值&lt;/h2&gt;

惰性求值(Lazy Evaluation)，说白了就是某些中间结果不需要被求出来，
求出来反而不利于后面的计算也浪费了时间。参见：惰性求值与惰性编程。
惰性求值是一个计算机编程中的一个概念，
它的目的是要最小化计算机要做的工作。惰性计算的最重要的好处是它可以构造一个无限的数据类型。
使用惰性求值的时候，表达式不在它被绑定到变量之后就立即求值，
而是在该值被取用的时候求值。语句如 x:=expression; (把一个表达式的结果赋值给一个变量)明显的调用这个表达式并把计算并把结果放置到 x 中，但是先不管实际在 x 中的是什么，直到通过后面的表达式中到 x 的引用而有了对它的值的需求的时候，而后面表达式自身的求值也可以被延迟，最终为了生成让外界看到的某个符号而计算这个快速增长的依赖树。

&lt;h2 id=&quot;闭包&quot;&gt;闭包&lt;/h2&gt;

闭包在计算机科学中，闭包（Closure）是词法闭包（Lexical Closure）的简称，
是引用了自由变量的函数。自由变量是在表达式中用于表示一个位置或一些位置的符号，
比如 f(x,y) 对 x 求偏导时，y就是自由变量。
这个被引用的自由变量将和这个函数一同存在，即使已经离开了创造它的环境也不例外。
在函数中(嵌套)定义另一个函数时，如果内部的函数引用了外部的函数的变量，
则可能产生闭包。运行时，一旦外部的 函数被执行，一个闭包就形成了，
闭包中包含了内部函数的代码，以及所需外部函数中的变量的引用。
其中所引用的变量称作上值(upvalue)。网上有很多讲 JavaScript 闭包的文章，如果你对 LISP 有系统的了解，那么这个概念自然会很清楚了。

快排的Racket实现

&lt;div class=&quot;language-racket highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;racket&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;quick-sort&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cond&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;empty?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;; 快排的思想是分治+递归&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;append&lt;/span&gt; 
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;quick-sort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
           &lt;span class=&quot;c1&quot;&gt;; 这里的 array 就是闭包   &lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;quick-sort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))]))&lt;/span&gt;
 
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;quick-sort&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;82&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; 运行结果 &apos;(0 1 2 3 3 4 4 5 5 9 82)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

通过这个例子，就可以感受到基于 lambda 算子的  Racket  语言强大的表达能力了。
高阶函数、lambda 表达式和闭包的使用使得 Racket 所描述的快排十分的精炼，
这和基于冯诺依曼模型C语言是迥然不容的思维模式。

&lt;h2 id=&quot;安装&quot;&gt;安装&lt;/h2&gt;

在 Racket 官网下载对应系统的安装包，安装完成后，就可以在命令行里使用 racket 命令。

&lt;h2 id=&quot;执行-racket-脚本&quot;&gt;执行 racket 脚本&lt;/h2&gt;

新建 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.rkt&lt;/code&gt; 文件：

&lt;div class=&quot;language-racket highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lisp&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

打开命令行，执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;racket -t hello.rkt&lt;/code&gt;, 就可以看到输出 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt;。
</description>
        <pubDate>Tue, 19 Mar 2013 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/welcome-to-racket/</link>
        <guid isPermaLink="true">https://wsdjeg.net/welcome-to-racket/</guid>
        
        <category>lisp</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>使用 Windows Live Writer 发布博客</title>
        <description>&lt;!-- prettier-ignore-start --&gt;


&lt;!-- prettier-ignore-end --&gt;

很早以前，使用 wordpress 搭建博客的时候，尝试过 Windows Live Writer 这个工具。一些操作界面记忆犹新。

&lt;img src=&quot;../images/windows-live-writer.jpg&quot; alt=&quot;window live writer&quot; /&gt;
&lt;img src=&quot;../images/windows-live-writer2.jpg&quot; alt=&quot;window live writer&quot; /&gt;

图片来源于网络。

早期的记录：

https://groups.google.com/g/ircubuntu-cn/c/CkxGsARUDV8

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;22:01:57 &amp;lt;Kandu&amp;gt; wsdjeg: wsdjeg.tk
22:02:06 &amp;lt;Kandu&amp;gt; wsdjeg: &amp;lt;img src=&quot;http://127.0.0.1/wordpress/wp-content/themes/twentyten/images/headers/path.jpg&quot;
22:02:07 &amp;lt;wsdjeg&amp;gt; 怎么了
22:02:35 &amp;lt;wsdjeg&amp;gt; 为什么不现实图片呢
22:02:46 &amp;lt;szsloss&amp;gt; 你的是什么服务器啊？？
22:02:54 &amp;lt;szsloss&amp;gt; apache or nginx??
22:03:12 &amp;lt;wsdjeg&amp;gt; 我自己的电脑阿
22:03:26 &amp;lt;wsdjeg&amp;gt; 不知道 ubuntu
22:03:31 &amp;lt;wsdjeg&amp;gt; 刚装的lamp
22:03:33 &amp;lt;szsloss&amp;gt; 要 环境的啊
22:03:35 &amp;lt;wsdjeg&amp;gt; 不会设置
22:03:37 &amp;lt;szsloss&amp;gt; 哦
22:03:43 &amp;lt;wsdjeg&amp;gt; 怎么杨设置阿
22:03:46 &amp;lt;szsloss&amp;gt; 那就是 apache 了】
22:03:50 &amp;lt;RuiZi&amp;gt; J :#ubuntu-cn
22:03:54 &amp;lt;myke2&amp;gt; Q :Read error: Connection reset by peer
22:04:05 &amp;lt;wsdjeg&amp;gt; 帮个忙 怎么设置 我就想做一个boog
22:04:20 &amp;lt;jiero&amp;gt; blog已经不流行了。
22:04:21 &amp;lt;jiero&amp;gt; 哈哈
22:04:43 &amp;lt;szsloss&amp;gt; 你 在 apache 里配置 一个 host 就可以了
22:04:45 &amp;lt;wsdjeg&amp;gt; 那该怎么设置下呢 有高手指点下么
22:04:54 &amp;lt;wsdjeg&amp;gt; 如何配置呢
Evanescence wsdjeg: you can set up Wordpress following official tutorial
Evanescence wsdjeg: and ubuntu wiki is usful too
22:06:27 &amp;lt;szsloss&amp;gt; wsdjeg: http://carrot.iteye.com/blog/232558
22:07:01 &amp;lt;szsloss&amp;gt; wsdjeg: http://clin003.com/servers/windows-configure-apache-virtualhost-1850/
22:07:09 &amp;lt;szsloss&amp;gt; 网上多的是啊
22:10:26 &amp;lt;wsdjeg&amp;gt; 还是高不明白
22:10:29 &amp;lt;shellex&amp;gt; ACTION 在咕噜牛奶
22:10:33 &amp;lt;bluek&amp;gt; sudo gedit /usr/share/gnome-session没有啊
22:10:48 &amp;lt;wsdjeg&amp;gt; 直接点阿 在什么地方加什么文件 内容是什么
22:11:48 &amp;lt;wsdjeg&amp;gt; 具体怎么弄阿 大哥
22:21:27 &amp;lt;caleb-&amp;gt; wsdjeg: 开了服务记得要设置防火墙
22:21:35 &amp;lt;caleb-&amp;gt; wsdjeg: 裸奔不是好习惯
22:21:48 &amp;lt;wsdjeg&amp;gt; 不懂
22:21:53 &amp;lt;wsdjeg&amp;gt; 怎么设置呢
22:22:18 &amp;lt;caleb-&amp;gt; wsdjeg: ubuntu 默认有图形介面的
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

感觉当年的聊天记录现在看了，都看不下去了，当时申请的 tk 域名，后期就没再用过。

虽然现在无法下载原来的 Windows Live Writer，但是感谢开源社区维护了一个开源的版本：&lt;a href=&quot;https://github.com/OpenLiveWriter/OpenLiveWriter&quot;&gt;OpenLiveWriter&lt;/a&gt;
</description>
        <pubDate>Fri, 20 May 2011 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/20110520/</link>
        <guid isPermaLink="true">https://wsdjeg.net/20110520/</guid>
        
        <category>blog</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>大学毕业了</title>
        <description>2006年，这一年我考上了苏州大学。家里人都非常高兴，就如同2003年那会儿考上了仪征中学一样。
在选择专业的时候第一志愿直接选择了生物科学专业，因为高中期间，几门课程当中生物课学的最好。
依然记得，新生报道是我的父亲陪同一起来的大学。
我们提前了一天来到了苏州，当时小姑姑住在白马涧那边，我们还去了白马涧公园玩了一下，河里的水清澈见底，还有桃花水母。

第二天，我和父亲一起来了学校报道。
报名好了整理完宿舍的时候，父亲再三叮嘱一些事情就离开了。
我也不太记得具体是什么事情，没过多久父亲又回来找到了我，他的脸色不太好，有些发白。
他没有说，其实我是知道的，父亲很少坐车出远门，折返回来坐车一定是晕车了。
父亲的话很少，仍然是叮嘱了那几句话就回去了，然而，这次叮嘱，明显感觉声音在哽咽。
从小打到，我记忆中就没见过父亲掉眼泪，他脾气其实不太好，和妈妈、爷爷奶奶经常拌嘴，
是个很要强的人，这是我记忆中第一次见到父亲落泪。想来也是，以往高中、
初中基本上就在家附近，哪怕是高中也是周末都回家，上了大学离家太远了。

我更新这篇日志是2024年，距离大学毕业过去了整整十四年。回过头来再看，
发现居然没人任何物件可以支撑这四年的记忆，回忆起来挺吃力的，感觉记忆也是零碎的，
前后错乱的，似乎都没有一个时间主线。依稀就记得那么一些人和事，可能再过几年，这些记忆应该慢慢会更加的淡化。

</description>
        <pubDate>Wed, 30 Jun 2010 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/graduated-from-Soochow-University/</link>
        <guid isPermaLink="true">https://wsdjeg.net/graduated-from-Soochow-University/</guid>
        
        <category>苏大</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>模块化 vimrc 初体验</title>
        <description>Vim 使用已经快有4个年头了，从最早期的只有一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.vimrc&lt;/code&gt; 文件，到之前一个完整的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.vim&lt;/code&gt; 目录，
期间配置文件结构也改变了很多。配置也变得越来越臃肿。

体验过 eclipse 这样的工具后，回过头来在看看 Vim 的配置，似乎也可以把一些功能做成一些模块，
然后根据自己实际的需求载入这些模块。

在这里，我们使用 Bundle 这款工具来管理插件，大致的思路如下：

&lt;h2 id=&quot;主文件结构&quot;&gt;主文件结构&lt;/h2&gt;

&lt;strong&gt;~/.vimrc:&lt;/strong&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;c&quot;&gt;&quot; 将插件管理器加入 rtp&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rtp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;+=~&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/.vim/&lt;/span&gt;bundle/bundle
&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; bundle#begin&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&quot; 模块逻辑&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:modulars&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;core&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;java&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&quot; 根据模块变量载入模块&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:modulars&lt;/span&gt;
    exe &lt;span class=&quot;s1&quot;&gt;&apos;so ~/.vim/modulars/&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;.vim&apos;&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;endfor&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; bundle#end&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;模块结构&quot;&gt;模块结构&lt;/h2&gt;

我们以 Java 模块为例：

&lt;strong&gt;~/.vim/modulars/java.vim:&lt;/strong&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Bundle &lt;span class=&quot;s1&quot;&gt;&apos;javautil.vim&apos;&lt;/span&gt;
Bundle &lt;span class=&quot;s1&quot;&gt;&apos;javaclass.vim&apos;&lt;/span&gt;


&lt;span class=&quot;c&quot;&gt;&quot; 插件配置&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:java_util_foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;xxx&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Wed, 01 Apr 2009 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/modular-vimrc/</link>
        <guid isPermaLink="true">https://wsdjeg.net/modular-vimrc/</guid>
        
        <category>vim</category>
        
        
        <category>工具分享</category>
        
      </item>
    
      <item>
        <title>Lua 数据库访问</title>
        <description></description>
        <pubDate>Fri, 20 Jun 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-database-access/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-database-access/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 面向对象</title>
        <description></description>
        <pubDate>Sat, 14 Jun 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-object-oriented/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-object-oriented/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 垃圾回收</title>
        <description>
Lua 采用了自动内存管理。 这意味着你不用操心新创建的对象需要的内存如何分配出来， 也不用考虑在对象不再被使用后怎样释放它们所占用的内存。

Lua 运行了一个垃圾收集器来收集所有死对象 （即在 Lua 中不可能再访问到的对象）来完成自动内存管理的工作。 Lua 中所有用到的内存，如：字符串、表、用户数据、函数、线程、 内部结构等，都服从自动管理。

Lua 实现了一个增量标记-扫描收集器。 它使用这两个数字来控制垃圾收集循环： 垃圾收集器间歇率和垃圾收集器步进倍率。 这两个数字都使用百分数为单位 （例如：值 100 在内部表示 1 ）。

垃圾收集器间歇率控制着收集器需要在开启新的循环前要等待多久。 增大这个值会减少收集器的积极性。 当这个值比 100 小的时候，收集器在开启新的循环前不会有等待。 设置这个值为 200 就会让收集器等到总内存使用量达到 之前的两倍时才开始新的循环。

垃圾收集器步进倍率控制着收集器运作速度相对于内存分配速度的倍率。 增大这个值不仅会让收集器更加积极，还会增加每个增量步骤的长度。 不要把这个值设得小于 100 ， 那样的话收集器就工作的太慢了以至于永远都干不完一个循环。 默认值是 200 ，这表示收集器以内存分配的”两倍”速工作。

如果你把步进倍率设为一个非常大的数字 （比你的程序可能用到的字节数还大 10% ）， 收集器的行为就像一个 stop-the-world 收集器。 接着你若把间歇率设为 200 ， 收集器的行为就和过去的 Lua 版本一样了： 每次 Lua 使用的内存翻倍时，就做一次完整的收集。
垃圾回收器函数

Lua 提供了以下函数collectgarbage ([opt [, arg]])用来控制自动内存管理:

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collectgarbage(&quot;collect&quot;)&lt;/code&gt;: 做一次完整的垃圾收集循环。通过参数 opt 它提供了一组不同的功能：&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collectgarbage(&quot;count&quot;)&lt;/code&gt;: 以 K 字节数为单位返回 Lua 使用的总内存数。 这个值有小数部分，所以只需要乘上 1024 就能得到 Lua 使用的准确字节数（除非溢出）。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collectgarbage(&quot;restart&quot;)&lt;/code&gt;: 重启垃圾收集器的自动运行。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collectgarbage(&quot;setpause&quot;)&lt;/code&gt;: 将 arg 设为收集器的 间歇率 （参见 §2.5）。 返回 间歇率 的前一个值。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collectgarbage(&quot;setstepmul&quot;)&lt;/code&gt;: 返回 步进倍率 的前一个值。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collectgarbage(&quot;step&quot;)&lt;/code&gt;: 单步运行垃圾收集器。 步长”大小”由 arg 控制。 传入 0 时，收集器步进（不可分割的）一步。 传入非 0 值， 收集器收集相当于 Lua 分配这些多（K 字节）内存的工作。 如果收集器结束一个循环将返回 true 。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collectgarbage(&quot;stop&quot;)&lt;/code&gt;: 停止垃圾收集器的运行。 在调用重启前，收集器只会因显式的调用运行。&lt;/li&gt;
&lt;/ul&gt;

以下演示了一个简单的垃圾回收实例:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;apple&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;orange&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;banana&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;collectgarbage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;count&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;collectgarbage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;count&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;collectgarbage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;collect&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;collectgarbage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;count&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行以上程序，输出结果如下(注意内存使用的变化)：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;20.9560546875
20.9853515625
0
19.4111328125
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Thu, 12 Jun 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-garbage-collection/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-garbage-collection/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 调试(Debug)</title>
        <description>
Lua 提供了 debug 库用于提供创建我们自定义调速器的功能。Lua 本身并未有内置的调速器，但很多开发者共享了他们的 Lua 调速器代码。

Lua 中 debug 库包含以下函数：

sethook ([thread,] hook, mask [, count]):

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug()&lt;/code&gt;: 进入一个用户交互模式，运行用户输入的每个字符串。 使用简单的命令以及其它调试设置，用户可以检阅全局变量和局部变量， 改变变量的值，计算一些表达式，等等。输入一行仅包含 cont 的字符串将结束这个函数， 这样调用者就可以继续向下运行。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getfenv(object)&lt;/code&gt;: 返回对象的环境变量。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gethook(optional thread)&lt;/code&gt;: 返回三个表示线程钩子设置的值： 当前钩子函数，当前钩子掩码，当前钩子计数&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getinfo ([thread,] f [, what])&lt;/code&gt;: 返回关于一个函数信息的表。 你可以直接提供该函数， 也可以用一个数字 f 表示该函数。 数字 f 表示运行在指定线程的调用栈对应层次上的函数： 0 层表示当前函数（getinfo 自身）； 1 层表示调用 getinfo 的函数 （除非是尾调用，这种情况不计入栈）；等等。 如果 f 是一个比活动函数数量还大的数字， getinfo 返回 nil。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug.getlocal ([thread,] f, local)&lt;/code&gt;: 此函数返回在栈的 f 层处函数的索引为 local 的局部变量 的名字和值。 这个函数不仅用于访问显式定义的局部变量，也包括形参、临时变量等。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getmetatable(value)&lt;/code&gt;: 把给定索引指向的值的元表压入堆栈。如果索引无效，或是这个值没有元表，函数将返回 0 并且不会向栈上压任何东西。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getregistry()&lt;/code&gt;: 返回注册表表，这是一个预定义出来的表， 可以用来保存任何 C 代码想保存的 Lua 值。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getupvalue (f, up)&lt;/code&gt;: 此函数返回函数 f 的第 up 个上值的名字和值。 如果该函数没有那个上值，返回 nil 。以 ‘(‘ （开括号）打头的变量名表示没有名字的变量 （去除了调试信息的代码块）。&lt;/li&gt;
  &lt;li&gt;将一个函数作为钩子函数设入。 字符串 mask 以及数字 count 决定了钩子将在何时调用。 掩码是由下列字符组合成的字符串，每个字符有其含义：
    &lt;ul&gt;
      &lt;li&gt;‘c’: 每当 Lua 调用一个函数时，调用钩子；&lt;/li&gt;
      &lt;li&gt;‘r’: 每当 Lua 从一个函数内返回时，调用钩子；&lt;/li&gt;
      &lt;li&gt;‘l’: 每当 Lua 进入新的一行时，调用钩子。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setlocal ([thread,] level, local, value)&lt;/code&gt;: 这个函数将 value 赋给 栈上第 level 层函数的第 local 个局部变量。 如果没有那个变量，函数返回 nil 。 如果 level 越界，抛出一个错误。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setmetatable (value, table)&lt;/code&gt;: 将 value 的元表设为 table （可以是 nil）。 返回 value。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setupvalue (f, up, value)&lt;/code&gt;: 这个函数将 value 设为函数 f 的第 up 个上值。 如果函数没有那个上值，返回 nil 否则，返回该上值的名字。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;traceback ([thread,] [message [, level]])&lt;/code&gt;: 如果 message 有，且不是字符串或 nil， 函数不做任何处理直接返回 message。 否则，它返回调用栈的栈回溯信息。 字符串可选项 message 被添加在栈回溯信息的开头。 数字可选项 level 指明从栈的哪一层开始回溯 （默认为 1 ，即调用 traceback 的那里）。&lt;/li&gt;
&lt;/ol&gt;

上表列出了我们常用的调试函数，接下来我们可以看些简单的例子：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;myfunction&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;debug.traceback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Stack trace&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;debug.getinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Stack trace end&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;myfunction&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;debug.getinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行以上代码输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Stack trace
stack traceback:
   test2.lua:2: in function &apos;myfunction&apos;
   test2.lua:8: in main chunk
    [C]: ?
table: 0054C6C8
Stack trace end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在以实例中，我们使用到了 debug 库的 traceback 和 getinfo 函数， getinfo 函数用于返回函数信息的表。
另一个实例

我们经常需要调试函数的内的局部变量。我们可以使用 getupvalue 函数来设置这些局部变量。实例如下：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;newCounter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newCounter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;repeat&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;debug.getupvalue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;debug.setupvalue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- if&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;until&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行以上代码输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1
2
index   1   k   =   1
index    2   n   =   2
11
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在以上实例中，计数器在每次调用时都会自增1。实例中我们使用了 getupvalue 函数查看局部变量的当前状态。我们可以设置局部变量为新值。实例中，在设置前 n 的值为 2,使用 setupvalue 函数将其设置为 10。现在我们调用函数，执行后输出为 11 而不是 3。
调试类型

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;命令行调试
图形界面调试
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

命令行调试器有：RemDebug、clidebugger、ctrace、xdbLua、LuaInterface - Debugger、Rldb、ModDebug。

图形界调试器有：SciTE、Decoda、ZeroBrane Studio、akdebugger、luaedit。
</description>
        <pubDate>Tue, 10 Jun 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-debug/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-debug/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 异常处理</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#语法错误&quot; id=&quot;markdown-toc-语法错误&quot;&gt;语法错误&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#运行错误&quot; id=&quot;markdown-toc-运行错误&quot;&gt;运行错误&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#pcall-和-xpcalldebug&quot; id=&quot;markdown-toc-pcall-和-xpcalldebug&quot;&gt;pcall 和 xpcall、debug&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

程序运行中错误处理是必要的，在我们进行文件操作，数据转移及web service
调用过程中都会出现不可预期的错误。如果不注重错误信息的处理，
就会造成信息泄露，程序无法运行等情况。

任何程序语言中，都需要错误处理。错误类型有：

&lt;ul&gt;
  &lt;li&gt;语法错误&lt;/li&gt;
  &lt;li&gt;运行错误&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;语法错误&quot;&gt;语法错误&lt;/h3&gt;

语法错误通常是由于对程序的组件（如运算符、表达式）使用不当引起的。一个简单的实例如下：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- test.lua 文件&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lua: test.lua:2: syntax error near &apos;==&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

正如你所看到的，以上出现了语法错误，一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; 号跟两个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; 号是有区别的。一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; 是赋值表达式两个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; 是比较运算。

另外一个实例:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行以上程序会出现如下错误：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lua: test2.lua:2: &apos;do&apos; expected near &apos;print&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

语法错误比程序运行错误更简单，运行错误无法定位具体错误，
而语法错误我们可以很快的解决，如以上实例我们只要在for语句下添加 do 即可：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;运行错误&quot;&gt;运行错误&lt;/h3&gt;

运行错误是程序可以正常执行，但是会输出报错信息。如下实例由于参数输入错误，程序执行时报错：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当我们编译运行以下代码时，编译是可以成功的，但在运行的时候会产生如下错误：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lua: test2.lua:2: attempt to perform arithmetic on local &apos;b&apos; (a nil value)
stack traceback:
 test2.lua:2: in function &apos;add&apos;
  test2.lua:5: in main chunk
    [C]: ?
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以下报错信息是由于程序缺少 b 参数引起的。
错误处理

我们可以使用两个函数：assert 和 error 来处理错误。实例如下：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;number&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a 不是一个数字&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;number&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;b 不是一个数字&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行以上程序会出现如下错误：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lua: test.lua:3: b 不是一个数字
stack traceback:
	[C]: in function &apos;assert&apos;
	test.lua:3: in local &apos;add&apos;
	test.lua:6: in main chunk
	[C]: in ?
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

实例中assert首先检查第一个参数，若没问题，assert不做任何事情；否则，assert以第二个参数作为错误信息抛出。

error函数语法格式：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;error (message [, level])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

功能：终止正在执行的函数，并返回message的内容作为错误信息(error函数永远都不会返回)

通常情况下，error会附加一些错误位置的信息到message头部。

Level参数指示获得错误的位置:

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Level=1[默认]：为调用error位置(文件+行号)
Level=2：指出哪个调用error的函数的函数
Level=0:不添加错误位置信息
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;pcall-和-xpcalldebug&quot;&gt;pcall 和 xpcall、debug&lt;/h3&gt;

Lua中处理错误，可以使用函数pcall（protected call）来包装需要执行的代码。

pcall接收一个函数和要传递个后者的参数，并执行，执行结果：有错误、无错误；返回值true或者或false, errorinfo。

语法格式如下

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if pcall(function_name, ….) then
-- 没有错误
else
-- 一些错误
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

简单实例：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; =pcall(function(i) print(i) end, 33)
33
true
   
&amp;gt; =pcall(function(i) print(i) error(&apos;error..&apos;) end, 33)
33
false        stdin:1: error..

&amp;gt; function f() return false,2 end
&amp;gt; if f() then print &apos;1&apos; else print &apos;0&apos; end
0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

pcall以一种”保护模式”来调用第一个参数，因此pcall可以捕获函数执行中的任何错误。

通常在错误发生时，希望落得更多的调试信息，而不只是发生错误的位置。但pcall返回时，它已经销毁了调用桟的部分内容。

Lua提供了xpcall函数，xpcall接收第二个参数——一个错误处理函数，当错误发生时，Lua会在调用桟展看（unwind）前调用错误处理函数，于是就可以在这个函数中使用debug库来获取关于错误的额外信息了。
debug库提供了两个通用的错误处理函数:

&lt;ul&gt;
  &lt;li&gt;debug.debug：提供一个Lua提示符，让用户来价差错误的原因&lt;/li&gt;
  &lt;li&gt;debug.traceback：根据调用桟来构建一个扩展的错误消息&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt;=xpcall(function(i) print(i) error(&apos;error..&apos;) end, function() print(debug.traceback()) end, 33) 33 stack traceback: stdin:1: in function [C]: in function &apos;error&apos; stdin:1: in function [C]: in function &apos;xpcall&apos; stdin:1: in main chunk [C]: in ? false nil
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

xpcall 使用实例 2:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;myfunction&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;myerrorhandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ERROR:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;xpcall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myfunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myerrorhandler&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行以上程序会出现如下错误：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ERROR: test2.lua:2: attempt to perform arithmetic on global &apos;n&apos; (a nil value)
false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 30 May 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-error-handling/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-error-handling/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 文件 IO</title>
        <description>
Lua I/O 库用于读取和处理文件。分为简单模式（和C一样）、完全模式。

&lt;ul&gt;
  &lt;li&gt;简单模式（simple model）拥有一个当前输入文件和一个当前输出文件，并且提供针对这些文件相关的操作。&lt;/li&gt;
  &lt;li&gt;完全模式（complete model） 使用外部的文件句柄来实现。它以一种面对对象的形式，将所有的文件操作定义为文件句柄的方法&lt;/li&gt;
&lt;/ul&gt;

简单模式在做一些简单的文件操作时较为合适。但是在进行一些高级的文件操作的时候，简单模式就显得力不从心。例如同时读取多个文件这样的操作，使用完全模式则较为合适。

打开文件操作语句如下：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;io.open&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

mode 的值有：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;模式&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;r&lt;/td&gt;
      &lt;td&gt;以只读方式打开文件，该文件必须存在。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;w&lt;/td&gt;
      &lt;td&gt;打开只写文件，若文件存在则文件长度清为0，即该文件内容会消失。若文件不存在则建立该文件。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;a&lt;/td&gt;
      &lt;td&gt;以附加的方式打开只写文件。若文件不存在，则会建立该文件，如果文件存在，写入的数据会被加到文件尾，即文件原先的内容会被保留。（EOF符保留）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;r+&lt;/td&gt;
      &lt;td&gt;以可读写方式打开文件，该文件必须存在。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;w+&lt;/td&gt;
      &lt;td&gt;打开可读写文件，若文件存在则文件长度清为零，即该文件内容会消失。若文件不存在则建立该文件。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;a+&lt;/td&gt;
      &lt;td&gt;与a类似，但此文件可读可写&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;b&lt;/td&gt;
      &lt;td&gt;二进制模式，如果文件是二进制文件，可以加上b&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;+&lt;/td&gt;
      &lt;td&gt;号表示对文件既可以读也可以写&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

简单模式

简单模式使用标准的 I/O 或使用一个当前输入文件和一个当前输出文件。

以下为 file.lua 文件代码，操作的文件为test.lua(如果没有你需要创建该文件)，代码如下：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 以只读方式打开文件&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;io.open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test.lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 设置默认输入文件为 test.lua&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;io.input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 输出文件第一行&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;io.read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 关闭打开的文件&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;io.close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 以附加的方式打开只写文件&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;io.open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test.lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 设置默认输出文件为 test.lua&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;io.output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 在文件最后一行添加 Lua 注释&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;io.write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;--  test.lua 文件末尾注释&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 关闭打开的文件&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;io.close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行以上代码，你会发现，输出了 test.ua 文件的第一行信息，并在该文件最后一行添加了 lua 的注释。如我这边输出的是：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-- test.lua 文件
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在以上实例中我们使用了 io.”x” 方法，其中 io.read() 中我们没有带参数，参数可以是下表中的一个：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;模式&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*n&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;读取一个数字并返回它。例：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file.read(&apos;*n&apos;)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*a&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;从当前位置读取整个文件。例：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file.read(&quot;*a&quot;)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*l&lt;/code&gt;（默认）&lt;/td&gt;
      &lt;td&gt;读取下一行，在文件尾 (EOF) 处返回 nil。例：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file.read(&quot;*l&quot;)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;返回一个指定字符个数的字符串，或在 EOF 时返回 nil。例：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file.read(5)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

其他的 io 方法有：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;io.tmpfile():返回一个临时文件句柄，该文件以更新模式打开，程序结束时自动删除

io.type(file): 检测obj是否一个可用的文件句柄

io.flush(): 向文件写入缓冲中的所有数据

io.lines(optional file name): 返回一个迭代函数,每次调用将获得文件中的一行内容,当到文件尾时，将返回nil,但不关闭文件
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

完全模式

通常我们需要在同一时间处理多个文件。我们需要使用 file:function_name 来代替 io.function_name 方法。以下实例演示了如同同时处理同一个文件:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 以只读方式打开文件&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;io.open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test.lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 输出文件第一行&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 关闭打开的文件&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 以附加的方式打开只写文件&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;io.open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test.lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 在文件最后一行添加 Lua 注释&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;--test&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 关闭打开的文件&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行以上代码，你会发现，输出了 test.ua 文件的第一行信息，并在该文件最后一行添加了 lua 的注释。如我这边输出的是：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-- test.lua 文件
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

read 的参数与简单模式一致。

其他方法:

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;file:seek(optional whence, optional offset): 设置和获取当前文件位置,成功则返回最终的文件位置(按字节),失败则返回nil加错误信息。参数 whence 值可以是:
    &quot;set&quot;: 从文件头开始
    &quot;cur&quot;: 从当前位置开始[默认]
    &quot;end&quot;: 从文件尾开始
    offset:默认为0
不带参数file:seek()则返回当前位置,file:seek(&quot;set&quot;)则定位到文件头,file:seek(&quot;end&quot;)则定位到文件尾并返回文件大小

file:flush(): 向文件写入缓冲中的所有数据

io.lines(optional file name): 打开指定的文件filename为读模式并返回一个迭代函数,每次调用将获得文件中的一行内容,当到文件尾时，将返回nil,并自动关闭文件。
若不带参数时io.lines() io.input():lines(); 读取默认输入设备的内容，但结束时不关闭文件,如

for line in io.lines(&quot;main.lua&quot;) do

　　print(line)

　　end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以下实例使用了 seek 方法，定位到文件倒数第 25 个位置并使用 read 方法的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*a&lt;/code&gt; 参数，即从当期位置(倒数第 25 个位置)读取整个文件。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 以只读方式打开文件&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;io.open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test.lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seek&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;end&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;*a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 关闭打开的文件&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

我这边输出的结果是：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;st.lua 文件末尾--test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Sat, 24 May 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-file-io/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-file-io/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 协同程序(coroutine)</title>
        <description>
什么是协同(coroutine)？

Lua 协同程序(coroutine)与线程比较类似：拥有独立的堆栈，独立的局部变量，独立的指令指针，同时又与其它协同程序共享全局变量和其它大部分东西。

协同是非常强大的功能，但是用起来也很复杂。

线程和协同程序区别

线程与协同程序的主要区别在于，一个具有多个线程的程序可以同时运行几个线程，而协同程序却需要彼此协作的运行。

在任一指定时刻只有一个协同程序在运行，并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起。

协同程序有点类似同步的多线程，在等待同一个线程锁的几个线程有点类似协同。

基本语法

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;方法&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;coroutine.create()&lt;/td&gt;
      &lt;td&gt;创建 coroutine，返回 coroutine， 参数是一个函数，当和 resume 配合使用的时候就唤醒函数调用&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;coroutine.resume()&lt;/td&gt;
      &lt;td&gt;重启 coroutine，和 create 配合使用&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;coroutine.yield()&lt;/td&gt;
      &lt;td&gt;挂起 coroutine，将 coroutine 设置为挂起状态，这个和 resume 配合使用能有很多有用的效果&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;coroutine.status()&lt;/td&gt;
      &lt;td&gt;查看 coroutine 的状态 注：coroutine 的状态有三种：dead，suspend，running，具体什么时候有这样的状态请参考下面的程序&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;coroutine.wrap（）&lt;/td&gt;
      &lt;td&gt;创建 coroutine，返回一个函数，一旦你调用这个函数，就进入 coroutine，和 create 功能重复&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;coroutine.running()&lt;/td&gt;
      &lt;td&gt;返回正在跑的 coroutine，一个 coroutine 就是一个线程，当使用 running 的时候，就是返回一个 corouting 的线程号&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

以下实例演示了以上各个方法的用法：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- coroutine_test.lua 文件&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;coroutine.create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;coroutine.resume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;-- 1&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;coroutine.status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;-- dead&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;----------&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;coroutine.wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;----------&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;co2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;coroutine.create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;coroutine.status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;--running&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;coroutine.running&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;--thread:XXXXXX&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;coroutine.yield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;coroutine.resume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;--1&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;coroutine.resume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;--2&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;coroutine.resume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;--3&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;coroutine.status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;-- suspended&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;coroutine.running&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;--nil&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;----------&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1
dead
----------
1
----------
1
2
3
running
thread: 0x7fb801c05868    false
suspended
thread: 0x7fb801c04c88    true
----------
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

coroutine.running 就可以看出来,coroutine 在底层实现就是一个线程。

当 create 一个 coroutine 的时候就是在新线程中注册了一个事件。

当使用 resume 触发事件的时候，create 的 coroutine 函数就被执行了，当遇到 yield 的时候就代表挂起当前线程，等候再次 resume 触发事件。

接下来我们分析一个更详细的实例：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;foo 函数输出&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;coroutine.yield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- 返回  2*a 的值&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;coroutine.create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;第一次协同程序执行输出&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- co-body 1 10&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;第二次协同程序执行输出&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;coroutine.yield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;-- a，b的值为第一次调用协同程序时传入&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;第三次协同程序执行输出&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;结束协同程序&quot;&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;-- b的值为第二次调用协同程序时传入&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;coroutine.resume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- true, 4&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;--分割线----&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;coroutine.resume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- true 11 -9&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;---分割线---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;coroutine.resume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- true 10 end&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;---分割线---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;coroutine.resume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- cannot resume dead coroutine&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;---分割线---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;第一次协同程序执行输出 1   10
foo 函数输出    2
main true    4
--分割线----
第二次协同程序执行输出   r
main true    11  -9
---分割线---
第三次协同程序执行输出  x   y
main true    10  结束协同程序
---分割线---
main false   cannot resume dead coroutine
---分割线---
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例接下如下：

&lt;ul&gt;
  &lt;li&gt;调用resume，将协同程序唤醒,resume操作成功返回true，否则返回false；&lt;/li&gt;
  &lt;li&gt;协同程序运行；&lt;/li&gt;
  &lt;li&gt;运行到yield语句；&lt;/li&gt;
  &lt;li&gt;yield挂起协同程序，第一次resume返回；（注意：此处yield返回，参数是resume的参数）&lt;/li&gt;
  &lt;li&gt;第二次resume，再次唤醒协同程序；（注意：此处resume的参数中，除了第一个参数，剩下的参数将作为yield的参数）&lt;/li&gt;
  &lt;li&gt;yield返回；&lt;/li&gt;
  &lt;li&gt;协同程序继续运行；&lt;/li&gt;
  &lt;li&gt;如果使用的协同程序继续运行完成后继续调用 resumev方法则输出：cannot resume dead coroutine&lt;/li&gt;
&lt;/ul&gt;

resume 和 yield 的配合强大之处在于，resume 处于主程中，它将外部状态（数据）传入到协同程序内部；而 yield 则将内部的状态（数据）返回到主程中。
生产者-消费者问题

现在我就使用 Lua 的协同程序来完成生产者-消费者这一经典问题。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newProductor&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;productor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
     &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;-- 将生产的物品发送给消费者&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;consumer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
          &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;-- 从生产者那里得到物品&lt;/span&gt;
          &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
     &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;coroutine.resume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newProductor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;nb&quot;&gt;coroutine.yield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;-- x表示需要发送的值，值返回以后，就挂起该协同程序&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 启动程序&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;newProductor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;coroutine.create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;productor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;consumer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
……
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Tue, 20 May 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-coroutine/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-coroutine/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 元表(Metatable)</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#__index-元方法&quot; id=&quot;markdown-toc-__index-元方法&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__index&lt;/code&gt; 元方法&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#__newindex-元方法&quot; id=&quot;markdown-toc-__newindex-元方法&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__newindex&lt;/code&gt; 元方法&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#__tostring-元方法&quot; id=&quot;markdown-toc-__tostring-元方法&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__tostring&lt;/code&gt; 元方法&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

在 Lua table 中我们可以访问对应的 key 来得到 value 值，但是却无法对两个 table 进行操作。

因此 Lua 提供了元表(Metatable)，允许我们改变 table 的行为，每个行为关联了对应的元方法。

例如，使用元表我们可以定义 Lua 如何计算两个 table 的相加操作 a+b。

当 Lua 试图对两个表进行相加时，先检查两者之一是否有元表，之后检查是否有一个叫&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__add&lt;/code&gt;的字段，若找到，则调用对应的值。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__add&lt;/code&gt; 等即时字段，其对应的值（往往是一个函数或是 table）就是”元方法”。

有两个很重要的函数来处理元表：

&lt;ul&gt;
  &lt;li&gt;setmetatable(table,metatable): 对指定 table 设置元表(metatable)，如果元表(metatable)中存在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__metatable&lt;/code&gt;键值，setmetatable 会失败 。&lt;/li&gt;
  &lt;li&gt;getmetatable(table): 返回对象的元表(metatable)。&lt;/li&gt;
&lt;/ul&gt;

以下实例演示了如何对指定的表设置元表：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;                          &lt;span class=&quot;c1&quot;&gt;-- 普通表&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;mymetatable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;                      &lt;span class=&quot;c1&quot;&gt;-- 元表&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;setmetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mymetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;-- 把 mymetatable 设为 mytable 的元表&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码也可以直接写成一行：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;setmetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({},{})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以下为返回对象元表：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;getmetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;-- 这回返回mymetatable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;__index-元方法&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__index&lt;/code&gt; 元方法&lt;/h2&gt;

这是 metatable 最常用的键。
当你通过键来访问 table 的时候，如果这个键没有值，那么 Lua 就会寻找该 table 的 metatable（假定有 metatable）中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__index&lt;/code&gt; 键。如果&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__index&lt;/code&gt;包含一个表格，Lua 会在表格中查找相应的键。

我们可以在使用 lua 命令进入交互模式查看：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ lua
Lua 5.3.0  Copyright (C) 1994-2015 Lua.org, PUC-Rio
&amp;gt; other = { foo = 3 }
&amp;gt; t = setmetatable({}, { __index = other })
&amp;gt; t.foo
3
&amp;gt; t.bar
nil
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__index&lt;/code&gt;包含一个函数的话，Lua 就会调用那个函数，table 和键会作为参数传递给函数。

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__index&lt;/code&gt; 元方法查看表中元素是否存在，如果不存在，返回结果为 nil；如果存在则由 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__index&lt;/code&gt; 返回结果。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;setmetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;value1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;__index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;key2&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;metatablevalue&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

实例输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;value1	metatablevalue
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

实例解析：

&lt;ul&gt;
  &lt;li&gt;
    mytable 表赋值为 {key1 = “value1”}。
  &lt;/li&gt;
  &lt;li&gt;
    mytable 设置了元表，元方法为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__index&lt;/code&gt;。
  &lt;/li&gt;
  &lt;li&gt;
    在 mytable 表中查找 key1，如果找到，返回该元素，找不到则继续。
  &lt;/li&gt;
  &lt;li&gt;
    在 mytable 表中查找 key2，如果找到，返回该元素，找不到则继续。
  &lt;/li&gt;
  &lt;li&gt;
    判断元表有没有&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__index&lt;/code&gt;方法，如果&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__index&lt;/code&gt;方法是一个函数，则调用该函数。元方法中查看是否传入 “key2” 键的参数（mytable.key2 已设置），如果传入 “key2” 参数返回 “metatablevalue”，否则返回 mytable 对应的键值。
  &lt;/li&gt;
&lt;/ul&gt;

我们可以将以上代码简单写成：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;setmetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;value1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;metatablevalue&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;__newindex-元方法&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__newindex&lt;/code&gt; 元方法&lt;/h2&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__newindex&lt;/code&gt; 元方法用来对表更新，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__index&lt;/code&gt;则用来对表访问 。

当你给表的一个缺少的索引赋值，解释器就会查找&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__newindex&lt;/code&gt; 元方法：如果存在则调用这个函数而不进行赋值操作。

以下实例演示了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__newindex&lt;/code&gt; 元方法的应用：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;mymetatable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;setmetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;value1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__newindex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mymetatable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newkey&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;新值2&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newkey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mymetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newkey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;新值1&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mymetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newkey1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;value1
nil    新值2
新值1    nil
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例中表设置了元方法 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__newindex&lt;/code&gt;，在对新索引键（newkey）赋值时（mytable.newkey = “新值 2”），会调用元方法，而不进行赋值。而如果对已存在的索引键（key1），则会进行赋值，而不调用元方法 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__newindex&lt;/code&gt;。

以下实例使用了 rawset 函数来更新表：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;setmetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;value1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;__newindex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;nb&quot;&gt;rawset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;new value&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;new value  &quot;4&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

为表添加操作符

以下实例演示了两表相加操作：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 计算表中最大值，table.maxn在Lua5.2以上版本中已无法使用&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 自定义计算表中最大值函数 table_maxn&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;table_maxn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;mn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mn&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 两表相加操作&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;setmetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;__add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newtable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table_maxn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newtable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table_maxn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newtable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;secondtable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secondtable&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1	1
2	2
3	3
4	4
5	5
6	6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__add&lt;/code&gt; 键包含在元表中，并进行相加操作。 表中对应的操作列表如下：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;模式&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__add&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;对应的运算符 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__sub&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;对应的运算符 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__mul&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;对应的运算符 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__div&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;对应的运算符 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__mod&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;对应的运算符 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__unm&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;对应的运算符 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__concat&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;对应的运算符 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;..&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__eq&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;对应的运算符 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__lt&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;对应的运算符 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__le&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;对应的运算符 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;=&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__call&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;元方法&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__call&lt;/code&gt; 元方法在 Lua 调用一个值时调用。以下实例演示了计算表中元素的和：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 计算表中最大值，table.maxn在Lua5.2以上版本中已无法使用&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 自定义计算表中最大值函数 table_maxn&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;table_maxn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;mn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mn&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 定义元方法__call&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;setmetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;__call&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newtable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table_maxn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table_maxn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newtable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newtable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;newtable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newtable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;70
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;__tostring-元方法&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__tostring&lt;/code&gt; 元方法&lt;/h2&gt;

&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__tostring&lt;/code&gt; 元方法用于修改表的输出行为。以下实例我们自定义了表的输出内容：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;setmetatable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;__tostring&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;表所有元素的和为 &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;表所有元素的和为 60
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

从本文中我们可以知道元表可以很好的简化我们的代码功能，所以了解 Lua 的元表，可以让我们写出更加简单优秀的 Lua 代码。
</description>
        <pubDate>Tue, 13 May 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-metatables/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-metatables/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 模块和包</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#加载机制&quot; id=&quot;markdown-toc-加载机制&quot;&gt;加载机制&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

模块类似于一个封装库，从 Lua 5.1 开始，Lua 加入了标准的模块管理机制，可以把一些公用的代码放在一个文件里，以 API 接口的形式在其他地方调用，有利于代码的重用和降低代码耦合度。

Lua 的模块是由变量、函数等已知元素组成的 table，因此创建一个模块很简单，就是创建一个 table，然后把需要导出的常量、函数放入其中，最后返回这个 table 就行。以下为创建自定义模块 module.lua，文件代码格式如下：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 文件名为 module.lua&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 定义一个名为 module 的模块&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 定义一个常量&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;这是一个常量&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 定义一个函数&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;func1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;io.write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;这是一个公有函数！&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;func2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;这是一个私有函数！&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;func3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;func2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

由上可知，模块的结构就是一个 table 的结构，因此可以像操作调用 table 里的元素那样来操作调用模块里的常量或函数。

上面的 func2 声明为程序块的局部变量，即表示一个私有函数，因此是不能从外部访问模块里的这个私有函数，必须通过模块里的公有函数来调用.
require 函数

Lua 提供了一个名为 require 的函数用来加载模块。要加载一个模块，只需要简单地调用就可以了。例如：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;模块名&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

或者

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;模块名&amp;gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

执行 require 后会返回一个由模块常量或函数组成的 table，并且还会定义一个包含该 table 的全局变量。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- test_module.php 文件&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- module 模块为上文提到到 module.lua&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;module&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;constant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;这是一个常量
这是一个私有函数！
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

或者给加载的模块定义一个别名变量，方便调用：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- test_module2.php 文件&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- module 模块为上文提到到 module.lua&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 别名变量 m&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;module&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;constant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;这是一个常量
这是一个私有函数！
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;加载机制&quot;&gt;加载机制&lt;/h3&gt;

对于自定义的模块，模块文件不是放在哪个文件目录都行，函数 require 有它自己的文件路径加载策略，它会尝试从 Lua 文件或 C 程序库中加载模块。

require 用于搜索 Lua 文件的路径是存放在全局变量 package.path 中，当 Lua 启动后，会以环境变量 LUA_PATH 的值来初始这个环境变量。如果没有找到该环境变量，则使用一个编译时定义的默认路径来初始化。

当然，如果没有 LUA_PATH 这个环境变量，也可以自定义设置，在当前用户根目录下打开 .profile 文件（没有则创建，打开 .bashrc 文件也可以），例如把 “~/lua/” 路径加入 LUA_PATH 环境变量里：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#LUA_PATH
export LUA_PATH=&quot;~/lua/?.lua;;&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

文件路径以 “;” 号分隔，最后的 2 个 “;;” 表示新加的路径后面加上原来的默认路径。

接着，更新环境变量参数，使之立即生效。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;source ~/.profile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这时假设 package.path 的值是：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/Users/dengjoe/lua/?.lua;./?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/lib/lua/5.1/?.lua;/usr/local/lib/lua/5.1/?/init.lua
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

那么调用 require(“module”) 时就会尝试打开以下文件目录去搜索目标。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/Users/dengjoe/lua/module.lua;
./module.lua
/usr/local/share/lua/5.1/module.lua
/usr/local/share/lua/5.1/module/init.lua
/usr/local/lib/lua/5.1/module.lua
/usr/local/lib/lua/5.1/module/init.lua
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果找过目标文件，则会调用 package.loadfile 来加载模块。否则，就会去找 C 程序库。

搜索的文件路径是从全局变量 package.cpath 获取，而这个变量则是通过环境变量 LUA_CPATH 来初始。

搜索的策略跟上面的一样，只不过现在换成搜索的是 so 或 dll 类型的文件。如果找得到，那么 require 就会通过 package.loadlib 来加载它。
C 包

Lua 和 C 是很容易结合的，使用 C 为 Lua 写包。

与 Lua 中写包不同，C 包在使用以前必须首先加载并连接，在大多数系统中最容易的实现方式是通过动态连接库机制。

Lua 在一个叫 loadlib 的函数内提供了所有的动态连接的功能。这个函数有两个参数:库的绝对路径和初始化函数。所以典型的调用的例子如下:

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;local path = &quot;/usr/local/lua/lib/libluasocket.so&quot;
local f = loadlib(path, &quot;luaopen_socket&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

loadlib 函数加载指定的库并且连接到 Lua，然而它并不打开库（也就是说没有调用初始化函数），反之他返回初始化函数作为 Lua 的一个函数，这样我们就可以直接在 Lua 中调用他。

如果加载动态库或者查找初始化函数时出错，loadlib 将返回 nil 和错误信息。我们可以修改前面一段代码，使其检测错误然后调用初始化函数：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/usr/local/lua/lib/libluasocket.so&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 或者 path = &quot;C:\\windows\\luasocket.dll&quot;，这是 Window 平台下&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loadlib&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;luaopen_socket&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;-- 真正打开库&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

一般情况下我们期望二进制的发布库包含一个与前面代码段相似的 stub 文件，安装二进制库的时候可以随便放在某个目录，只需要修改 stub 文件对应二进制库的实际路径即可。

将 stub 文件所在的目录加入到 LUA_PATH，这样设定后就可以使用 require 函数加载 C 库了。

</description>
        <pubDate>Sat, 10 May 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-modules-packages/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-modules-packages/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua tables（表）</title>
        <description></description>
        <pubDate>Mon, 28 Apr 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-tables/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-tables/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 迭代器</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#泛型-for-迭代器&quot; id=&quot;markdown-toc-泛型-for-迭代器&quot;&gt;泛型 for 迭代器&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#无状态的迭代器&quot; id=&quot;markdown-toc-无状态的迭代器&quot;&gt;无状态的迭代器&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

迭代器（iterator）是一种对象，它能够用来遍历标准模板库容器中的部分或全部元素，每个迭代器对象代表容器中的确定的地址

在 Lua 中迭代器是一种支持指针类型的结构，它可以遍历集合的每一个元素。

&lt;h3 id=&quot;泛型-for-迭代器&quot;&gt;泛型 for 迭代器&lt;/h3&gt;

泛型 for 在自己内部保存迭代函数，实际上它保存三个值：迭代函数、状态常量、控制变量。

泛型 for 迭代器提供了集合的 key/value 对，语法格式如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;for k, v in pairs(t) do
    print(k, v)
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上面代码中，k, v 为变量列表；pairs(t)为表达式列表。

查看以下实例:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Tutorial&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1  Lua
2  Tutorial
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例中我们使用了 Lua 默认提供的迭代函数 ipairs。

下面我们看看范性 for 的执行过程：

&lt;ul&gt;
  &lt;li&gt;首先，初始化，计算 in 后面表达式的值，表达式应该返回范性 for 需要的三个值：迭代函数、状态常量、控制变量；与多值赋值一样，如果表达式返回的结果个数不足三个会自动用 nil 补足，多出部分会被忽略。&lt;/li&gt;
  &lt;li&gt;第二，将状态常量和控制变量作为参数调用迭代函数（注意：对于 for 结构来说，状态常量没有用处，仅仅在初始化时获取他的值并传递给迭代函数）。&lt;/li&gt;
  &lt;li&gt;第三，将迭代函数返回的值赋给变量列表。&lt;/li&gt;
  &lt;li&gt;第四，如果返回的第一个值为 nil 循环结束，否则执行循环体。&lt;/li&gt;
  &lt;li&gt;第五，回到第二步再次调用迭代函数&lt;/li&gt;
&lt;/ul&gt;

在 Lua 中我们常常使用函数来描述迭代器，每次调用该函数就返回集合的下一个元素。Lua 的迭代器包含以下两种类型：

&lt;ul&gt;
  &lt;li&gt;无状态的迭代器&lt;/li&gt;
  &lt;li&gt;多状态的迭代器&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;无状态的迭代器&quot;&gt;无状态的迭代器&lt;/h3&gt;

无状态的迭代器是指不保留任何状态的迭代器，因此在循环中我们可以利用无状态迭代器避免创建闭包花费额外的代价。

每一次迭代，迭代函数都是用两个变量（状态常量和控制变量）的值作为参数被调用，一个无状态的迭代器只利用这两个值可以获取下一个元素。

这种无状态迭代器的典型的简单的例子是 ipairs，他遍历数组的每一个元素。

以下实例我们使用了一个简单的函数来实现迭代器，实现 数字 n 的平方：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;square&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iteratorMaxCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;currentNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentNumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iteratorMaxCount&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;currentNumber&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentNumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentNumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;currentNumber&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;square&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1	1
2	4
3	9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

迭代的状态包括被遍历的表（循环过程中不会改变的状态常量）和当前的索引下标（控制变量），ipairs 和迭代函数都很简单，我们在 Lua 中可以这样实现：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;iter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
       &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ipairs&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

当 Lua 调用 ipairs(a)开始循环时，他获取三个值：迭代函数 iter、状态常量 a、控制变量初始值 0；然后 Lua 调用 iter(a,0)返回 1,a[1]（除非 a[1]=nil）；第二次迭代调用 iter(a,1)返回 2,a[2]……直到第一个 nil 元素。
多状态的迭代器

很多情况下，迭代器需要保存多个状态信息而不是简单的状态常量和控制变量，最简单的方法是使用闭包，还有一种方法就是将所有的状态信息封装到 table 内，将 table 作为迭代器的状态常量，因为这种情况下可以将所有的信息存放在 table 内，所以迭代函数通常不需要第二个参数。

以下实例我们创建了自己的迭代器：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Tutorial&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;elementIterator&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
   &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collection&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;-- 闭包函数&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
         &lt;span class=&quot;c1&quot;&gt;--  返回迭代器的当前元素&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elementIterator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Lua
Tutorial
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上实例中我们可以看到，elementIterator 内使用了闭包函数，实现计算集合大小并输出各个元素。
</description>
        <pubDate>Sun, 20 Apr 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-iterators/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-iterators/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 数组</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#一维数组&quot; id=&quot;markdown-toc-一维数组&quot;&gt;一维数组&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#多维数组&quot; id=&quot;markdown-toc-多维数组&quot;&gt;多维数组&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

数组，就是相同数据类型的元素按一定顺序排列的集合，可以是一维数组和多维数组。

Lua 数组的索引键值可以使用整数表示，数组的大小不是固定的。

&lt;h2 id=&quot;一维数组&quot;&gt;一维数组&lt;/h2&gt;

一维数组是最简单的数组，其逻辑结构是线性表。一维数组可以用 for 循环出数组中的元素，如下实例：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Tutorial&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nil
Lua
Tutorial
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

正如你所看到的，我们可以使用整数索引来访问数组元素，如果知道的索引没有值则返回 nil。

在 Lua 索引值是以 1 为起始，但你也可以指定 0 开始。

除此外我们还可以以负数为数组索引值：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-4
-2
0
2
4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;多维数组&quot;&gt;多维数组&lt;/h2&gt;

多维数组即数组中包含数组或一维数组的索引键对应一个数组。

以下是一个三行三列的阵列多维数组：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 初始化数组&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 访问数组&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1
2
3
2
4
6
3
6
9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

不同索引键的三行三列阵列多维数组：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 初始化数组&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;maxRows&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;maxColumns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxRows&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxColumns&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxColumns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 访问数组&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxRows&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxColumns&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxColumns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1
2
3
2
4
6
3
6
9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

正如你所看到的，以上的实例中，数组设定了指定的索引值，这样可以避免出现 nil 值，有利于节省内存空间。

</description>
        <pubDate>Mon, 14 Apr 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-arrays/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-arrays/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 字符串</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#字符串操作&quot; id=&quot;markdown-toc-字符串操作&quot;&gt;字符串操作&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#字符串操作-1&quot; id=&quot;markdown-toc-字符串操作-1&quot;&gt;字符串操作&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#stringupper&quot; id=&quot;markdown-toc-stringupper&quot;&gt;string.upper&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

字符串或串(String)是由数字、字母、下划线组成的一串字符。

Lua 语言中字符串可以使用以下三种方式来表示：

&lt;ul&gt;
  &lt;li&gt;单引号间的一串字符。&lt;/li&gt;
  &lt;li&gt;双引号间的一串字符。&lt;/li&gt;
  &lt;li&gt;[[和]]间的一串字符。&lt;/li&gt;
&lt;/ul&gt;

以上三种方式的字符串实例如下：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;string1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;字符串 1 是&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;string2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;lua&apos;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;字符串 2 是&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;n&quot;&gt;string3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[[&quot;Lua 教程&quot;]]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;字符串 3 是&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;字符串 1 是&quot;	Hello
字符串 2 是	lua
字符串 3 是	&quot;Lua 教程&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

转义字符用于表示不能直接显示的字符，比如后退键，回车键，等。如在字符串转换双引号可以使用 “&quot;“。

所有的转义字符和所对应的意义：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;转义字符&lt;/th&gt;
      &lt;th&gt;意义&lt;/th&gt;
      &lt;th&gt;ASCII 码值（十进制）&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;\a&lt;/td&gt;
      &lt;td&gt;响铃(BEL)&lt;/td&gt;
      &lt;td&gt;007&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\b&lt;/td&gt;
      &lt;td&gt;退格(BS) ，将当前位置移到前一列&lt;/td&gt;
      &lt;td&gt;008&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\f&lt;/td&gt;
      &lt;td&gt;换页(FF)，将当前位置移到下页开头&lt;/td&gt;
      &lt;td&gt;012&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\n&lt;/td&gt;
      &lt;td&gt;换行(LF) ，将当前位置移到下一行开头&lt;/td&gt;
      &lt;td&gt;010&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\r&lt;/td&gt;
      &lt;td&gt;回车(CR) ，将当前位置移到本行开头&lt;/td&gt;
      &lt;td&gt;013&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\t&lt;/td&gt;
      &lt;td&gt;水平制表(HT) （跳到下一个 TAB 位置）&lt;/td&gt;
      &lt;td&gt;009&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\v&lt;/td&gt;
      &lt;td&gt;垂直制表(VT)&lt;/td&gt;
      &lt;td&gt;011&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\&lt;/td&gt;
      &lt;td&gt;代表一个反斜线字符’’&apos;&lt;/td&gt;
      &lt;td&gt;092&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&apos;&lt;/td&gt;
      &lt;td&gt;代表一个单引号（撇号）字符&lt;/td&gt;
      &lt;td&gt;039&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&quot;&lt;/td&gt;
      &lt;td&gt;代表一个双引号字符&lt;/td&gt;
      &lt;td&gt;034&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;空字符(NULL)&lt;/td&gt;
      &lt;td&gt;000&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\ddd&lt;/td&gt;
      &lt;td&gt;1 到 3 位八进制数所代表的任意字符&lt;/td&gt;
      &lt;td&gt;三位八进制&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;\xhh&lt;/td&gt;
      &lt;td&gt;1 到 2 位十六进制所代表的任意字符&lt;/td&gt;
      &lt;td&gt;二位十六进制&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;字符串操作&quot;&gt;字符串操作&lt;/h2&gt;

Lua 提供了很多的方法来支持字符串的操作：

字符串大小写转换

以下实例演示了如何对字符串大小写进行转换：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;string1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.upper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;LUA
lua
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

字符串查找与反转

以下实例演示了如何对字符串进行查找与反转操作：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Lua Tutorial&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 查找字符串&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Tutorial&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;reversedString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string.reverse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;新字符串为&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reversedString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;5    12
新字符串为   lairotuT auL
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

字符串格式化

以下实例演示了如何对字符串进行格式化操作：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;string1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Lua&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;string2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Tutorial&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;number1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;number2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 基本字符串格式化&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;基本格式化 %s %s&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 日期格式化&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;month&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2014&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;日期格式化 %02d/%02d/%03d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 十进制格式化&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;%.4f&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;基本格式化 Lua Tutorial
日期格式化 02/01/2014
0.3333
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

字符与整数相互转换

以下实例演示了字符与整数相互转换：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 字符转换&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 转换第一个字符&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 转换第三个字符&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 转换末尾第一个字符&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 第二个字符&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 转换末尾第二个字符&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;


&lt;span class=&quot;c1&quot;&gt;-- 整数 ASCII 码转换为字符&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;97&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;76
97
97
117
117
a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

其他常用函数

以下实例演示了其他字符串操作，如计算字符串长度，字符串连接，字符串复制等：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;string1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;wsdjeg.&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;string2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;spacevim&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;string3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.org&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 使用 .. 进行字符串连接&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;连接字符串&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;c1&quot;&gt;-- 字符串长度&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;字符串长度 &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;


&lt;span class=&quot;c1&quot;&gt;-- 字符串复制 2 次&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;repeatedString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;string.rep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;repeatedString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;连接字符串	wsdjeg.spacevim.org
字符串长度 	8
spacevimspacevim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;字符串操作-1&quot;&gt;字符串操作&lt;/h2&gt;

Lua 提供了很多的方法来支持字符串的操作：

&lt;h3 id=&quot;stringupper&quot;&gt;string.upper&lt;/h3&gt;

字符串全部转为大写字母。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;string.upper(argument)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

示例：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;str1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;wsdjeg&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string.upper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

输出：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;WSDJEG
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Tue, 08 Apr 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-strings/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-strings/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 运算符</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#算术运算符&quot; id=&quot;markdown-toc-算术运算符&quot;&gt;算术运算符&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#关系运算符&quot; id=&quot;markdown-toc-关系运算符&quot;&gt;关系运算符&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

运算符是一个特殊的符号，用于告诉解释器执行特定的数学或逻辑运算。Lua 提供了以下几种运算符类型：

&lt;ul&gt;
  &lt;li&gt;算术运算符&lt;/li&gt;
  &lt;li&gt;关系运算符&lt;/li&gt;
  &lt;li&gt;逻辑运算符&lt;/li&gt;
  &lt;li&gt;其他运算符&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;算术运算符&quot;&gt;算术运算符&lt;/h2&gt;

下表列出了 Lua 语言中的常用算术运算符，设定 A 的值为 10，B 的值为 20：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;操作符&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
      &lt;th&gt;实例&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;加法&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A + B&lt;/code&gt; 输出结果 30&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;减法&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A - B&lt;/code&gt; 输出结果 -10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;乘法&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A * B&lt;/code&gt; 输出结果 200&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;除法&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B / A&lt;/code&gt; 输出结果 2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;取余&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B % A&lt;/code&gt; 输出结果 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;乘幂&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A ^ 2&lt;/code&gt; 输出结果 100&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;负号&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-A&lt;/code&gt; 输出结果 -10&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

实例

我们可以通过以下实例来更加透彻的理解算术运算符的应用：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;21&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 1 - c 的值为 &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 2 - c 的值为 &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 3 - c 的值为 &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 4 - c 的值为 &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 5 - c 的值为 &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 6 - c 的值为 &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 7 - c 的值为 &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上程序执行结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Line 1 - c 的值为 31
Line 2 - c 的值为 11
Line 3 - c 的值为 210
Line 4 - c 的值为 2.1
Line 5 - c 的值为 1
Line 6 - c 的值为 441
Line 7 - c 的值为 -21
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;关系运算符&quot;&gt;关系运算符&lt;/h2&gt;

下表列出了 Lua 语言中的常用关系运算符，设定 A 的值为 10，B 的值为 20：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;操作符&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
      &lt;th&gt;实例&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;==&lt;/td&gt;
      &lt;td&gt;等于，检测两个值是否相等，相等返回 true，否则返回 false&lt;/td&gt;
      &lt;td&gt;(A == B) 为 false。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;~=&lt;/td&gt;
      &lt;td&gt;不等于，检测两个值是否相等，相等返回 false，否则返回 true&lt;/td&gt;
      &lt;td&gt;(A ~= B) 为 true。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;gt;&lt;/td&gt;
      &lt;td&gt;大于，如果左边的值大于右边的值，返回 true，否则返回 false&lt;/td&gt;
      &lt;td&gt;(A &amp;gt; B) 为 false。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;&lt;/td&gt;
      &lt;td&gt;小于，如果左边的值大于右边的值，返回 false，否则返回 true&lt;/td&gt;
      &lt;td&gt;(A &amp;lt; B) 为 true。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;gt;=&lt;/td&gt;
      &lt;td&gt;大于等于，如果左边的值大于等于右边的值，返回 true，否则返回 false&lt;/td&gt;
      &lt;td&gt;(A &amp;gt;= B) is not true.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&amp;lt;=&lt;/td&gt;
      &lt;td&gt;小于等于， 如果左边的值小于等于右边的值，返回 true，否则返回 false&lt;/td&gt;
      &lt;td&gt;(A &amp;lt;= B) is true.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

实例

我们可以通过以下实例来更加透彻的理解关系运算符的应用：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;21&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 1 - a 等于 b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 1 - a 不等于 b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 2 - a 不等于 b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 2 - a 等于 b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 3 - a 小于 b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 3 - a 大于等于 b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 4 - a 大于 b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 5 - a 小于等于 b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 修改 a 和 b 的值&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 5 - a 小于等于  b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Line 6 - b 大于等于 a&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上程序执行结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Line 1 - a 不等于 b
Line 2 - a 不等于 b
Line 3 - a 大于等于 b
Line 4 - a 大于 b
Line 5 - a 小于等于 b
Line 6 - b 大于等于 a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Fri, 28 Mar 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-miscellaneous-operator/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-miscellaneous-operator/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 函数</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#多返回值&quot; id=&quot;markdown-toc-多返回值&quot;&gt;多返回值&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#可变参数&quot; id=&quot;markdown-toc-可变参数&quot;&gt;可变参数&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

在 Lua 中，函数是对语句和表达式进行抽象的主要方法。既可以用来处理一些特殊的工作，也可以用来计算一些值。

Lua 提供了许多的内建函数，你可以很方便的在程序中调用它们，如 print()函数可以将传入的参数打印在控制台上。

Lua 函数主要有两种用途：

&lt;ol&gt;
  &lt;li&gt;完成指定的任务，这种情况下函数作为调用语句使用；&lt;/li&gt;
  &lt;li&gt;计算并返回值，这种情况下函数作为赋值语句的表达式使用。&lt;/li&gt;
&lt;/ol&gt;

函数定义

Lua 编程语言函数定义格式如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)
   function_body
 return result_params_comma_separated
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

解析：

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;optional_function_scope&lt;/code&gt;: 该参数是可选的制定函数是全局函数还是局部函数，未设置该参数末尾为全局函数，如果你需要设置函数为局部函数需要使用关键字 local。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function_name&lt;/code&gt;: 指定函数名称。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;argument1, argument2, argument3..., argumentn&lt;/code&gt; : 函数参数，多个参数以逗号隔开，函数也可以不带参数。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function_body&lt;/code&gt;: 函数体，函数中需要执行的代码语句块。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;result_params_comma_separated&lt;/code&gt;: 函数返回值，Lua 语言函数可以返回多个值，每个值以逗号隔开。&lt;/li&gt;
&lt;/ul&gt;

实例

以下实例定义了函数 max()，参数为 num1, num2，用于比较两值的大小，并返回最大值：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;--[[ 函数返回两个值的最大值 --]]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- 调用函数&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;两值比较最大值为 &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;两值比较最大值为 &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果为：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57593287-5174b980-756d-11e9-867c-a1754ec68988.png&quot; alt=&quot;max&quot; /&gt;

Lua 中我们可以将函数作为参数传递给函数，如下实例：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;myprint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;这是打印函数 -   ##&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;##&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;functionPrint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num2&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;-- 调用传递的函数参数&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;functionPrint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;myprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- myprint 函数作为参数传递&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果为：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57593302-63565c80-756d-11e9-9e55-f8dc2177a253.png&quot; alt=&quot;function&quot; /&gt;

&lt;h2 id=&quot;多返回值&quot;&gt;多返回值&lt;/h2&gt;

Lua 函数可以返回多个结果值，比如 string.find，其返回匹配串”开始和结束的下标”（如果不存在匹配串返回 nil）。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; s, e = string.find(&quot;www.w3cschool.cn&quot;, &quot;w3cschool&quot;)
&amp;gt; print(s, e)
5	13
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

Lua 函数中，在 return 后列出要返回的值得列表即可返回多值，如：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;maximum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;             &lt;span class=&quot;c1&quot;&gt;-- 最大值索引&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;-- 最大值&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
       &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;mi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;
       &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mi&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maximum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果为：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57593257-373adb80-756d-11e9-8b28-d578035cf2aa.png&quot; alt=&quot;maximum&quot; /&gt;

&lt;h2 id=&quot;可变参数&quot;&gt;可变参数&lt;/h2&gt;

Lua 函数可以接受可变数目的参数，和 C 语言类似在函数参数列表中使用三点（…) 表示函数有可变的参数。

Lua 将函数的参数放在一个叫 arg 的表中，#arg 表示传入参数的个数。

例如，我们计算几个数的平均值：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;average&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
   &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;总共传入 &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; 个数&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;平均值为&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;average&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果为：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57593230-1bcfd080-756d-11e9-98b1-e4f515980e6d.png&quot; alt=&quot;average&quot; /&gt;
</description>
        <pubDate>Thu, 20 Mar 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-functions/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-functions/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 流程控制</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#if-语句&quot; id=&quot;markdown-toc-if-语句&quot;&gt;if 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#if-else-语句&quot; id=&quot;markdown-toc-if-else-语句&quot;&gt;if else 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#else-if-语句&quot; id=&quot;markdown-toc-else-if-语句&quot;&gt;else if 语句&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#if-else-嵌套&quot; id=&quot;markdown-toc-if-else-嵌套&quot;&gt;if else 嵌套&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

Lua 编程语言流程控制语句通过程序设定一个或多个条件语句来设定。在条件为 true 时执行指定程序代码，在条件为 false 时执行其他指定代码。

控制结构的条件表达式结果可以是任何值，Lua 认为 false 和 nil 为假，true 和非 nil 为真。

要注意的是 Lua 中 0 为 true：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;--[ 0 为true ]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0 为真&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0 为真
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

Lua 提供了以下控制结构语句：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;语句&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;if 语句&lt;/td&gt;
      &lt;td&gt;if 语句 由一个布尔表达式作为条件判断，其后紧跟其他语句组成。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;if…else 语句&lt;/td&gt;
      &lt;td&gt;if 语句 可以与 else 语句搭配使用, 在 if 条件表达式为 false 时执行 else 语句代码。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;if 嵌套语句&lt;/td&gt;
      &lt;td&gt;你可以在 if 或 else if 中使用一个或多个 if 或 else if 语句 。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;if-语句&quot;&gt;if 语句&lt;/h2&gt;

Lua if 语句 由一个布尔表达式作为条件判断，其后紧跟其他语句组成。

Lua if 语句语法格式如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if(布尔表达式)
then
   --[ 在布尔表达式为 true 时执行的语句 --]
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在布尔表达式为 true 时会 if 中的代码块会被执行，在布尔表达式为 false 时，紧跟在 if 语句 end 之后的代码会被执行。

Lua 认为 false 和 nil 为假，true 和非 nil 为真。要注意的是 Lua 中 0 为 true。

实例

以下实例用于判断变量 a 的值是否小于 20：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;--[ 定义变量 --]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;--[ 使用 if 语句 --]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;--[ if 条件为 true 时打印以下信息 --]&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a 小于 20&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a 的值为:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果如下：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57591306-4ddc3500-7563-11e9-90b7-a477f11add54.png&quot; alt=&quot;if&quot; /&gt;

&lt;h2 id=&quot;if-else-语句&quot;&gt;if else 语句&lt;/h2&gt;

Lua if 语句可以与 else 语句搭配使用, 在 if 条件表达式为 false 时执行 else 语句代码块。

Lua if…else 语句语法格式如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if(布尔表达式)
then
   --[ 布尔表达式为 true 时执行该语句块 --]
else
   --[ 布尔表达式为 false 时执行该语句块 --]
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在布尔表达式为 true 时会 if 中的代码块会被执行，在布尔表达式为 false 时，else 的代码块会被执行。

Lua 认为 false 和 nil 为假，true 和非 nil 为真。要注意的是 Lua 中 0 为 true。

实例

以下实例用于判断变量 a 的值：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;--[ 定义变量 --]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;--[ 检查条件 --]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;--[ if 条件为 true 时执行该语句块 --]&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a 小于 20&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;--[ if 条件为 false 时执行该语句块 --]&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a 大于 20&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a 的值为 :&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果如下：

&lt;h2 id=&quot;else-if-语句&quot;&gt;else if 语句&lt;/h2&gt;

Lua if 语句可以与 else if…else 语句搭配使用, 在 if 条件表达式为 false 时执行 else if…else 语句代码块，用于检测多个条件语句。

Lua if…else if…else 语句语法格式如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if( 布尔表达式 1)
then
   --[ 在布尔表达式 1 为 true 时执行该语句块 --]

else if( 布尔表达式 2)
   --[ 在布尔表达式 2 为 true 时执行该语句块 --]

else if( 布尔表达式 3)
   --[ 在布尔表达式 3 为 true 时执行该语句块 --]
else
   --[ 如果以上布尔表达式都不为 true 则执行该语句块 --]
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

示例代码，以下示例代码对变量 a 值进行判断：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;--[ 定义变量 --]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;--[ 检查布尔条件 --]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;--[ 如果条件为 true 打印以下信息 --]&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a 的值为 10&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;--[ if else if 条件为 true 时打印以下信息 --]&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a 的值为 20&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;--[ if else if condition 条件为 true 时打印以下信息 --]&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a 的值为 30&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;--[ 以上条件语句没有一个为 true 时打印以下信息 --]&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;没有匹配 a 的值&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a 的真实值为: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

运行结果如下：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57591705-4d449e00-7565-11e9-97dd-a6c4c667597b.png&quot; alt=&quot;elseif&quot; /&gt;

&lt;h2 id=&quot;if-else-嵌套&quot;&gt;if else 嵌套&lt;/h2&gt;

Lua if 语句允许嵌套, 这就意味着你可以在一个 if 或 else if 语句中插入其他的 if 或 else if 语句。
Lua if 嵌套语句语法格式如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if( 布尔表达式 1)
then
   --[ 布尔表达式 1 为 true 时执行该语句块 --]
   if(布尔表达式 2)
   then
      --[ 布尔表达式 2 为 true 时执行该语句块 --]
   end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

你可以用同样的方式嵌套 else if…else 语句。

实例

以下实例用于判断变量 a 和 b 的值：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;--[ 定义变量 --]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;--[ 检查条件 --]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;--[ if 条件为 true 时执行以下 if 条件判断 --]&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;--[ if 条件为 true 时执行该语句块 --]&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a 的值为 100 b 的值为 200&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a 的值为 :&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;b 的值为 :&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码执行结果如下：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57592594-1d4bc980-756a-11e9-894b-fe6137424a6d.png&quot; alt=&quot;ififif&quot; /&gt;

</description>
        <pubDate>Thu, 13 Mar 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-decision-making/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-decision-making/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 循环</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#while-循环&quot; id=&quot;markdown-toc-while-循环&quot;&gt;while 循环&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#for-循环&quot; id=&quot;markdown-toc-for-循环&quot;&gt;for 循环&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#数值-for-循环&quot; id=&quot;markdown-toc-数值-for-循环&quot;&gt;数值 for 循环&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#泛型-for-循环&quot; id=&quot;markdown-toc-泛型-for-循环&quot;&gt;泛型 for 循环&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#repeat-until-循环&quot; id=&quot;markdown-toc-repeat-until-循环&quot;&gt;repeat until 循环&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#嵌套循环&quot; id=&quot;markdown-toc-嵌套循环&quot;&gt;嵌套循环&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#循环控制语句&quot; id=&quot;markdown-toc-循环控制语句&quot;&gt;循环控制语句&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

很多情况下我们需要做一些有规律性的重复操作，因此在程序中就需要重复执行某些语句。

一组被重复执行的语句称之为循环体，能否继续重复，决定循环的终止条件。

循环结构是在一定条件下反复执行某段程序的流程结构，被反复执行的程序被称为循环体。

循环语句是由循环体及循环的终止条件两部分组成的。

Lua 语言提供了以下几种循环处理方式：

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;循环类型&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;while 循环&lt;/td&gt;
      &lt;td&gt;在条件为 true 时，让程序重复地执行某些语句。执行语句前会先检查条件是否为 true。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;for 循环&lt;/td&gt;
      &lt;td&gt;重复执行指定语句，重复次数可在 for 语句中控制。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Lua repeat…until&lt;/td&gt;
      &lt;td&gt;重复执行循环，直到 指定的条件为真时为止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;循环嵌套&lt;/td&gt;
      &lt;td&gt;可以在循环内嵌套一个或多个循环语句（while、for、do..while）&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;while-循环&quot;&gt;while 循环&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;while(condition)
do
   statements
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

statements(循环体语句) 可以是一条或多条语句，condition(条件) 可以是任意表达式，在 condition(条件) 为 true 时执行循环体语句。

示例：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a 的值为:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57582840-49306600-74fc-11e9-82e9-9d75b35c7cb5.png&quot; alt=&quot;whileloop&quot; /&gt;

&lt;h2 id=&quot;for-循环&quot;&gt;for 循环&lt;/h2&gt;

Lua 编程语言中 for 循环语句可以重复执行指定语句，重复次数可在 for 语句中控制。

Lua 编程语言中 for 语句有两大类：：

&lt;ul&gt;
  &lt;li&gt;数值 for 循环&lt;/li&gt;
  &lt;li&gt;泛型 for 循环&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;数值-for-循环&quot;&gt;数值 for 循环&lt;/h3&gt;

基本语法：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;for var=exp1,exp2,exp3 do
    &amp;lt;执行体&amp;gt;
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

var 从 exp1 变化到 exp2，每次变化以 exp3 为步长递增 var，并执行一次”执行体”。exp3 是可选的，如果不指定，默认为 1。

实例：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

for 的三个表达式在循环开始前一次性求值，以后不再进行求值。比如上面的 f(x)只会在循环开始前执行一次，其结果用在后面的循环中。

验证如下:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;方法被执行&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;泛型-for-循环&quot;&gt;泛型 for 循环&lt;/h4&gt;

泛型 for 循环通过一个迭代器函数来遍历所有值，类似 java 中的 foreach 语句。

Lua 编程语言中泛型 for 循环语法格式:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;--打印数组a的所有值&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

示例：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;days&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Suanday&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Monday&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Tuesday&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ipairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;days&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;  &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;repeat-until-循环&quot;&gt;repeat until 循环&lt;/h2&gt;

Lua 编程语言中 repeat…until 循环语句不同于 for 和 while 循环，for 和 while 循环的
条件语句在当前循环执行开始时判断，而 repeat…until 循环的条件语句在当前循环结束后判断。

基本语法格式：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;repeat
   statements
until( condition )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

我们注意到循环条件判断语句（condition）在循环体末尾部分，所以在条件进行判断前循环体都会执行一次。
如果条件判断语句（condition）为 false，循环会重新开始执行，直到条件判断语句（condition）为 true 才会停止执行。

示例代码：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;--[ 变量定义 --]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;--[ 执行循环 --]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;repeat&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a的值为:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;until&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

允许结果如下：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57583373-65cf9c80-7502-11e9-821e-e8f929aaad45.png&quot; alt=&quot;repeat&quot; /&gt;

&lt;h2 id=&quot;嵌套循环&quot;&gt;嵌套循环&lt;/h2&gt;

Lua 编程语言中允许循环中嵌入循环。以下实例演示了 Lua 循环嵌套的应用。
语法

Lua 编程语言中 for 循环嵌套语法格式:

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;for init,max/min value, increment
do
   for init,max/min value, increment
   do
      statements
   end
   statements
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

Lua 编程语言中 while 循环嵌套语法格式:

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;while(condition)
do
   while(condition)
   do
      statements
   end
   statements
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

Lua 编程语言中 repeat…until 循环嵌套语法格式:

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;repeat
   statements
   repeat
      statements
   until( condition )
until( condition )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

除了以上同类型循环嵌套外，我们还可以使用不同的循环类型来嵌套，如 for 循环体中嵌套 while 循环。
实例

以下实例使用了 for 循环嵌套:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
         &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;i 的值为：&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

运行结果如下：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57583680-703f6580-7505-11e9-82d3-581b024f58ad.png&quot; alt=&quot;luawhilefor&quot; /&gt;

&lt;h2 id=&quot;循环控制语句&quot;&gt;循环控制语句&lt;/h2&gt;

lua 支持 break 语句，退出当前循环或语句，并开始脚本执行紧接着的语句:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;--[ 定义变量 --]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;--[ while 循环 --]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a 的值为:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;--[ 使用 break 语句终止循环 --]&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 09 Mar 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-loops/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-loops/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 数据类型</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#nil空&quot; id=&quot;markdown-toc-nil空&quot;&gt;nil（空）&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#boolean布尔&quot; id=&quot;markdown-toc-boolean布尔&quot;&gt;boolean（布尔）&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#number数字&quot; id=&quot;markdown-toc-number数字&quot;&gt;number（数字）&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#string字符串&quot; id=&quot;markdown-toc-string字符串&quot;&gt;string（字符串）&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#table表&quot; id=&quot;markdown-toc-table表&quot;&gt;table（表）&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#function函数&quot; id=&quot;markdown-toc-function函数&quot;&gt;function（函数）&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#thread线程&quot; id=&quot;markdown-toc-thread线程&quot;&gt;thread（线程）&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#userdata自定义类型&quot; id=&quot;markdown-toc-userdata自定义类型&quot;&gt;userdata（自定义类型）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

Lua 是动态类型语言，变量不要类型定义,只需要为变量赋值。 值可以存储在变量中，作为参数传递或结果返回。

Lua 中有 8 个基本类型分别为：nil、boolean、number、string、userdata、function、thread 和 table。

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;数据类型&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;nil&lt;/td&gt;
      &lt;td&gt;这个最简单，只有值 nil 属于该类，表示一个无效值（在条件表达式中相当于 false）。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;boolean&lt;/td&gt;
      &lt;td&gt;包含两个值：false 和 true。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;number&lt;/td&gt;
      &lt;td&gt;表示双精度类型的实浮点数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;string&lt;/td&gt;
      &lt;td&gt;字符串由一对双引号或单引号来表示&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;function&lt;/td&gt;
      &lt;td&gt;由 C 或 Lua 编写的函数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;userdata&lt;/td&gt;
      &lt;td&gt;表示任意存储在变量中的 C 数据结构&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;thread&lt;/td&gt;
      &lt;td&gt;表示执行的独立线路，用于执行协同程序&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;table&lt;/td&gt;
      &lt;td&gt;Lua 中的表（table）其实是一个”关联数组”（associative arrays），数组的索引可以是数字或者是字符串。在 Lua 里，table 的创建是通过”构造表达式”来完成，最简单构造表达式是{}，用来创建一个空表。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

我们可以使用 type 函数测试给定变量或者值的类型

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Hello world&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;--&amp;gt; string&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;             &lt;span class=&quot;c1&quot;&gt;--&amp;gt; number&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;              &lt;span class=&quot;c1&quot;&gt;--&amp;gt; function&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;--&amp;gt; function&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;--&amp;gt; boolean&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;                &lt;span class=&quot;c1&quot;&gt;--&amp;gt; nil&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;--&amp;gt; string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;nil空&quot;&gt;nil（空）&lt;/h2&gt;

nil 类型表示一种没有任何有效值，它只有一个值 – nil，例如打印一个没有赋值的变量，便会输出一个 nil 值：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; print(type(a))
nil
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

对于全局变量和 table，nil 还有一个”删除”作用，给全局变量或者 table 表里的变量赋一个 nil 值，等同于把它们删掉，执行下面代码就知：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tab1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;val1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;val2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;val3&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tab1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; - &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;tab1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tab1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; - &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57571049-900a5700-743b-11e9-9691-e99f610d1769.png&quot; alt=&quot;lua nil&quot; /&gt;

&lt;h2 id=&quot;boolean布尔&quot;&gt;boolean（布尔）&lt;/h2&gt;

boolean 类型只有两个可选值：true（真） 和 false（假），Lua 把 false 和 nil 看作是”假”，其他的都为”真”:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;false and nil are false!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;other is true!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57571099-2dfe2180-743c-11e9-8737-bce16161cb88.png&quot; alt=&quot;luaboolean&quot; /&gt;

&lt;h2 id=&quot;number数字&quot;&gt;number（数字）&lt;/h2&gt;

Lua 默认只有一种 number 类型 – double（双精度）类型（默认类型可以修改 luaconf.h 里的定义），以下几种写法都被看作是 number 类型：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2e+1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2e-1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;8263692594256e-06&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57571118-6a318200-743c-11e9-868b-2501a4503440.png&quot; alt=&quot;luanumber&quot; /&gt;

&lt;h2 id=&quot;string字符串&quot;&gt;string（字符串）&lt;/h2&gt;

字符串由一对双引号或单引号来表示。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;string1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;this is string1&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;string2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;this is string2&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

也可以用 2 个方括号 “[[]]” 来表示”一块”字符串。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[[
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;a href=&quot;//www.w3cschool.cn/&quot;&amp;gt;w3cschoolW3Cschool教程&amp;lt;/a&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
]]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57571136-ad8bf080-743c-11e9-95b7-6ef63f121761.png&quot; alt=&quot;luastring&quot; /&gt;

在对一个数字字符串上进行算术操作时，Lua 会尝试将这个数字字符串转成一个数字:

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; print(&quot;2&quot; + 6)
8.0
&amp;gt; print(&quot;2&quot; + &quot;6&quot;)
8.0
&amp;gt; print(&quot;2 + 6&quot;)
2 + 6
&amp;gt; print(&quot;-2e2&quot; * &quot;6&quot;)
-1200.0
&amp;gt; print(&quot;error&quot; + 1)
stdin:1: attempt to perform arithmetic on a string value
stack traceback:
 stdin:1: in main chunk
    [C]: in ?
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

以上代码中”error” + 1 执行报错了，字符串连接使用的是 .. ，如：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; print(&quot;a&quot; .. &apos;b&apos;)
ab
&amp;gt; print(157 .. 428)
157428
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

使用 # 来计算字符串的长度，放在字符串前面，如下实例：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; len = &quot;www.w3cschool.cn&quot;
&amp;gt; print(#len)
16
&amp;gt; print(#&quot;www.w3cschool.cn&quot;)
16
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;table表&quot;&gt;table（表）&lt;/h2&gt;

在 Lua 里，table 的创建是通过”构造表达式”来完成，最简单构造表达式是{}，用来创建一个空表。也可以在表里添加一些数据，直接初始化表:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 创建一个空的 table&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tbl1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- 直接初始表&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tbl2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;apple&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;pear&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;orange&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;grape&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

Lua 中的表（table）其实是一个”关联数组”（associative arrays），数组的索引可以是数字或者是字符串。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- table_test.lua 脚本文件&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;value&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;22&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; : &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

脚本执行结果为：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57571278-77e80700-743e-11e9-8129-64922e0f5844.png&quot; alt=&quot;luatable&quot; /&gt;

不同于其他语言的数组把 0 作为数组的初始索引，在 Lua 里表的默认初始索引一般以 1 开始。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- table_test2.lua 脚本文件&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tbl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;apple&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;pear&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;orange&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;grape&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tbl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

脚本执行结果为：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57571292-98b05c80-743e-11e9-9870-0d1b29550caa.png&quot; alt=&quot;table&quot; /&gt;

table 不会固定长度大小，有新数据添加时 table 长度会自动增长，没初始的 table 都是 nil。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- table_test3.lua 脚本文件&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;a3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;val&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

脚本执行结果为：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57571301-cac1be80-743e-11e9-8cbe-fd5fd467f8ad.png&quot; alt=&quot;table3&quot; /&gt;

&lt;h2 id=&quot;function函数&quot;&gt;function（函数）&lt;/h2&gt;

在 Lua 中，函数是被看作是”第一类值（First-Class Value）”，函数可以存在变量里:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- function_test.lua 脚本文件&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;factorial1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;factorial1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;factorial1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;factorial2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;factorial1&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;factorial2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

脚本执行结果为：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57571311-f0e75e80-743e-11e9-9da0-05391afc4db8.png&quot; alt=&quot;luafunction&quot; /&gt;

function 可以以匿名函数（anonymous function）的方式通过参数传递:

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- function_test2.lua 脚本文件&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;anonymous&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;pairs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tab&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;val1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;val2&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;anonymous&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; = &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

脚本执行结果为：

&lt;img src=&quot;https://user-images.githubusercontent.com/13142418/57571319-0bb9d300-743f-11e9-920f-d6536eac6eec.png&quot; alt=&quot;luafunction2&quot; /&gt;

&lt;h2 id=&quot;thread线程&quot;&gt;thread（线程）&lt;/h2&gt;

在 Lua 里，最主要的线程是协同程序（coroutine）。它跟线程（thread）差不多，拥有自己独立的栈、局部变量和指令指针，可以跟其他协同程序共享全局变量和其他大部分东西。

线程跟协程的区别：线程可以同时多个运行，而协程任意时刻只能运行一个，并且处于运行状态的协程只有被挂起（suspend）时才会暂停。

&lt;h2 id=&quot;userdata自定义类型&quot;&gt;userdata（自定义类型）&lt;/h2&gt;

userdata 是一种用户自定义数据，用于表示一种由应用程序或 C/C++ 语言库所创建的类型，可以将任意 C/C++ 的任意数据类型的数据（通常是 struct 和 指针）存储到 Lua 变量中调用。
</description>
        <pubDate>Wed, 13 Feb 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-data-types/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-data-types/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>Lua 基本语法</title>
        <description>&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#注释&quot; id=&quot;markdown-toc-注释&quot;&gt;注释&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#标识符&quot; id=&quot;markdown-toc-标识符&quot;&gt;标识符&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#关键词&quot; id=&quot;markdown-toc-关键词&quot;&gt;关键词&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#全局变量&quot; id=&quot;markdown-toc-全局变量&quot;&gt;全局变量&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

Lua 提供了交互式编程模式和脚本式编程模式，交互式编程模式可以在命令行中直接输入代码并查看结果。
Lua 的交互式编程可通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lua -i&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lua&lt;/code&gt; 命令开启。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;F:\languages&amp;gt;lua
Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

在命令行中，输入以下命令:

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; print(&quot;hello world!&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

按下回车后可以看到执行结果如下：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; print(&quot;hello world!&quot;)
hello world!
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

脚本式编程，指的是，将代码写入文件后并执行，比如新建 hello.lua 文件，并写入以下内容：

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;hello world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

使用 lua 执行以上脚本，输出结果为：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;F:\languages\lua&amp;gt;lua hello.lua
hello world!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

我们也可以在 lua 文件顶部添加执行命令，比如，添加

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/local/bin/lua
print(&quot;hello world!&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

然后通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./hello.lua&lt;/code&gt; 的方式来执行。

&lt;h2 id=&quot;注释&quot;&gt;注释&lt;/h2&gt;

Lua 的注释分单行注释和多行注释，单行注释以两个减号开头

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- 这是一个单行注释&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;hello world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

多行注释在段落前后分别有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--[[&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--]]&lt;/code&gt;。

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;--[[
这是一个多行注释
这是一个多行注释
--]]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;hello world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;标识符&quot;&gt;标识符&lt;/h2&gt;

Lua 标识符用于定义一个变量、函数的名称。标示符以一个字母 A 到 Z 或 a 到 z 或下划线 _ 开头后加上 0 个或多个字母，下划线，数字（0 到 9）。

最好不要使用下划线加大写字母的标示符，因为 Lua 的保留字也是这样的。

Lua 不允许使用特殊字符如 @, $, 和 % 来定义标示符。

Lua 是一个区分大小写的编程语言。因此在 Lua 中 W3c 与 w3c 是两个不同的标示符。

以下列出了一些正确的标示符：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mohd         zara      abc     move_name    a_123
myname50     _temp     j       a23b9        retVal
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;关键词&quot;&gt;关键词&lt;/h2&gt;

Lua 本身一些保留的关键字是不可以使用的，比如循环用到的 for while 等。

以下列出了 Lua 的保留关键字。保留关键字不能作为常量或变量或其他用户自定义标示符：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;| and      | break | do    | else   |
| elseif   | end   | false | for    |
| function | if    | in    | local  |
| nil      | not   | or    | repeat |
| return   | then  | true  | until  |
| while    |
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;全局变量&quot;&gt;全局变量&lt;/h2&gt;

Lua 的默认情况下变量总是全局变量，全局变量也不需要声明，直接赋值即可，访问一个未赋值即不存在的全局变量，
也不会报错，只不过得到的是：nil

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; print(b)
nil
&amp;gt; b=10
&amp;gt; print(b)
10
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

如果你想删除一个全局变量，只需要将变量赋值为 nil。

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; b = nil
&amp;gt; print(b)
nil
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

这样变量 b 就好像从没被使用过一样。换句话说, 当且仅当一个变量不等于 nil 时，这个变量即存在。
</description>
        <pubDate>Sat, 09 Feb 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/lua-basic-syntax/</link>
        <guid isPermaLink="true">https://wsdjeg.net/lua-basic-syntax/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>学习 Lua 脚本语言</title>
        <description>&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

大学期间，和朋友一起玩过一段时间《魔兽世界》，这款游戏的插件都是使用 lua 来写的。
当时折腾插件时经常莫名其妙报错。于是，就想着要不自己也学习下 lua，然后也可以自己写一些插件。

&lt;h2 id=&quot;开始学习&quot;&gt;开始学习&lt;/h2&gt;

最初的时候，其实并没有太多的在线教程，只能硬着头皮看官方的手册。好在 lua 算是比较简单的语言。

电脑上是 Ubuntu 7.04 LTS 版本，装上 lua 和 Vim 这两个工具后，就开始学着写一些简单的脚本了。

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-basic-syntax/&quot;&gt;Lua 基本语法&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-data-types/&quot;&gt;Lua 数据类型&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-loops/&quot;&gt;Lua 循环&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-decision-making/&quot;&gt;Lua 流程控制&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-functions/&quot;&gt;Lua 函数&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-miscellaneous-operator/&quot;&gt;Lua 运算符&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-strings/&quot;&gt;Lua 字符串&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-arrays/&quot;&gt;Lua 数组&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-iterators/&quot;&gt;Lua 迭代器&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-tables/&quot;&gt;Lua tables（表）&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-modules-packages/&quot;&gt;Lua 模块和包&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-metatables/&quot;&gt;Lua 元表(Metatable)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-coroutine/&quot;&gt;Lua 协同程序(coroutine)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-file-io/&quot;&gt;Lua 文件 IO&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-error-handling/&quot;&gt;Lua 异常处理&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-debug/&quot;&gt;Lua 调试(Debug)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-garbage-collection/&quot;&gt;Lua 垃圾回收&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-object-oriented/&quot;&gt;Lua 面向对象&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;../lua-database-access/&quot;&gt;Lua 数据库访问&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 03 Feb 2008 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/learn-lua-script/</link>
        <guid isPermaLink="true">https://wsdjeg.net/learn-lua-script/</guid>
        
        <category>lua</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>大学选修课《Java 编程》</title>
        <description>大学的专业是生物科学，本以为选修课会选一个实验相关的课程。科室不知道为什么鬼使神差的选了一个 Java 的。
这个似乎和生物没有一丁点关系。

感觉可能是因为以前接触过 C 语言，多多少少对编程还有一点了解，以前的兴趣死灰复燃。

C 语言更多的是面向过程编程，经常是把一个过程分离成多个函数来写。但是 Java 完全不一样，
面向对象编程这个思想，也是第一次听说。

在 Java 里，一切都是对象，做任何事情之前，得先有对象，然后通过对象来执行某件事。

第一节课上的似乎非常无趣，第一个程序是死记硬背下来的。

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;People&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]){&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello world!&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Wed, 11 Oct 2006 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/java-elective-course/</link>
        <guid isPermaLink="true">https://wsdjeg.net/java-elective-course/</guid>
        
        <category>java</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>进入苏州大学的第一天</title>
        <description>都说上有天堂，下有苏杭。第一次来到苏州，市区的环境真的没有想像中的那么好。
21 号报到，提前 1 天来到了苏州，正好姑姑在苏州这边工作，去玩了一天。
恰逢啤酒节，白马涧公园晚上也很热闹。

第二天早晨，免费进园玩了一会。早晨的空气非常好，小溪里的桃花水母晶莹剔透。

办好报到，收拾好宿舍，父亲就回去了。临走是分明看到父亲的眼睛是红的，
也许是因为第一次长时间出远门，自己心里也非常堵，似乎一点没有入学的开心氛围。
</description>
        <pubDate>Mon, 21 Aug 2006 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/first-day-in-Soochow-University/</link>
        <guid isPermaLink="true">https://wsdjeg.net/first-day-in-Soochow-University/</guid>
        
        <category>苏大</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>高中毕业了</title>
        <description>转眼间，高中毕业了。这三年来对我来说起伏还是很大的。刚进高中的时候，成绩还是中等偏上，上课也非常认真。可惜高一的化学、历史太枯燥无味，完全是死记硬背东西，一点兴趣也没有。那时地理跟政治两门课学的挺轻松。以至于后来上课打瞌睡，政治老师都不叫我了。

也不记得是什么时候开始迷上玩游戏的，03年那会，检查还不严，随随便便都可以去上网，后来04年就严了，未成年基本上肯定不让上网了。那时候玩的最多的是大话西游跟梦幻西游，这两游戏账号到现在还在呢。

什么样的通宵经历都有了，中午去上网的也有，下午下课后直接去的也有，晚自习下课去的也有。连续通宵一周的也有了。甚至有一次通宵完了回来第二天是考试的也有。

高一高二两年，真的把各种玩游戏的方式都体验了个遍。

高二期末考试结束，班上阿连问我考多少，结果我是倒数第二，他倒数第一，还被他笑了一通。也就是那一次让我彻底破防了，怎么说也是初中班里第二名靠近来的，这回去没法交差啦。于是，在学校后面租了一个房间，彻底戒掉网游，高考前再也不去上网了。暑假前后两个月，埋头苦学，恶补。60天结束第一次月考，考了班上第一名，班主任差点觉得我是作弊的😂，往后基本上就是前三来来去去就再也没什么大的变动了。

高考结束了哪天，晚上我又去上网啦，上了一夜回来被老爸骂了一通，不过想来，似乎也完全没瘾了。
</description>
        <pubDate>Fri, 30 Jun 2006 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/20060630/</link>
        <guid isPermaLink="true">https://wsdjeg.net/20060630/</guid>
        
        <category>回忆</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>不要轻言放弃</title>
        <description>
高中2年时间过去了，这两年时间玩了太多时间，学习完全是荒废了，期末考试成绩非常差，差到自己已经完全不相信了。
甚至有一种想自暴自弃的感觉。

但是，看到家人期许的眼神，看到父亲忙碌的背影，觉得自己错的太离谱了。

是的，这个暑假，学校有补习课，一个人住在学校后面的小屋子里，早起晚睡，
没日没夜的看书，写模拟试卷，总算感觉稍微充实一点了。

</description>
        <pubDate>Thu, 01 Sep 2005 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/never-give-up/</link>
        <guid isPermaLink="true">https://wsdjeg.net/never-give-up/</guid>
        
        <category>高中</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>分班选生物还是化学</title>
        <description>
高一这一年过的很快，这一年没有用心学习，玩的太多了，到了高二分班的时候了。
记得初中升高中的时候，化学考的比物理都高，以为以后会一直喜欢化学这门课的。

可是完全没有想到的是，目前政治这门课成绩最好，然后是地理课，再然后是物理。

总结下来，高一的历史和化学死背的东西太多，逻辑性的东西太少，所以不喜欢，成绩自然也就落下了。

难不成要学文科？！！

不行，坚决不学文科，选一个物理吧，这个目前还算跟得上。再选一个新的课程，生物。
</description>
        <pubDate>Wed, 01 Sep 2004 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/biological-or-chemical/</link>
        <guid isPermaLink="true">https://wsdjeg.net/biological-or-chemical/</guid>
        
        <category>vim</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>Vim 环视和固化分组</title>
        <description>&lt;!-- prettier-ignore-start --&gt;


&lt;!-- prettier-ignore-end --&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;vim&lt;/th&gt;
      &lt;th&gt;Perl&lt;/th&gt;
      &lt;th&gt;意义&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\@=&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(?=&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;顺序环视&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\@!&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(?!&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;顺序否定环视&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\@&amp;lt;=&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(?&amp;lt;=&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;逆序环视&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\@&amp;lt;!&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(?&amp;lt;!&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;逆序否定环视&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\@&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(?&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;固化分组&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\%(atom\)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(?:&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;非捕获型括号&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

和 perl 稍有不同的是，vim 中的环视和固化分组的模式的位置与 perl 不同。 例如，查找紧跟在 foo 之后的 bar，perl 将模式写在环视的括号内， 而 vim 将模式写在环视的元字符之前。
Perl 的写法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/(?&amp;lt;=foo)bar/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

vim 的写法

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/\(foo\)\@&amp;lt;=bar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;strong&gt;Vim 使用示例&lt;/strong&gt;

&lt;ul&gt;
  &lt;li&gt;顺序环视
查找后面是 sql 的 my： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/my\(sql\)\@=&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;顺序否定环视
查找后面不是 sql 的 my：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/my\(sql\)\@!&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;逆序环视
查找前面是 my 的 sql： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/\(my\)\@&amp;lt;=sql&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;逆序否定环视
查找前面不是 my 的 sql： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/\(my\)\@&amp;lt;!sql&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;固化分组&lt;/li&gt;
  &lt;li&gt;非捕获型括号
意思是，此分组不捕获，可以理解为不算在分组信息中&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:%s/\%(my\)sql\(ok\)/\1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

上面的命令会将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mysqlok&lt;/code&gt; 替换为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ok&lt;/code&gt; ，由于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my&lt;/code&gt; 为捕获在分组中，故组中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\1&lt;/code&gt; 为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ok&lt;/code&gt;。
</description>
        <pubDate>Sun, 01 Aug 2004 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/vim-regular-expression-look-around-and-solidified-group/</link>
        <guid isPermaLink="true">https://wsdjeg.net/vim-regular-expression-look-around-and-solidified-group/</guid>
        
        <category>vim</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>最后一封信</title>
        <description>今天收到一份来自刘雅月信，非常的意外。记得高一刚开始的时候，一次在操场上，
看到一个女孩子摔倒了，鬼使神差地跑过去递了纸巾。

想到马上要分班了，也挺失落的。
</description>
        <pubDate>Wed, 30 Jun 2004 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/20040630/</link>
        <guid isPermaLink="true">https://wsdjeg.net/20040630/</guid>
        
        <category>高中</category>
        
        
        <category>生活随笔</category>
        
      </item>
    
      <item>
        <title>Lisp 编程语言相关知识</title>
        <description>利用暑假的时间，简单学习了解了下 Lisp 这一编程语言，也可以说这一类编程语言。

&lt;h2 id=&quot;初识-lisp&quot;&gt;初识 Lisp&lt;/h2&gt;

Lisp 是一种历史悠久的、函数式编程语言举个简单的例子：

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;安装-scheme&quot;&gt;安装 Scheme&lt;/h2&gt;

从 Scheme 官网下载安装包： https://groups.csail.mit.edu/mac/ftpdir/scheme-7.5/#Download

下周安装完成后，可以使用 mit-scheme 命令调用。

&lt;h2 id=&quot;运行-scm-文件&quot;&gt;运行 scm 文件&lt;/h2&gt;

在 MIT-Scheme 中输入 code 非常麻烦，光标不能回退和上下移动，所以比较简单的方法就是运行已经写完的文件：

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mit-scheme -load yourfile.scm 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Tue, 01 Jul 2003 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/the-related-knowledge-of-lisp/</link>
        <guid isPermaLink="true">https://wsdjeg.net/the-related-knowledge-of-lisp/</guid>
        
        <category>lisp</category>
        
        
        <category>学习笔记</category>
        
      </item>
    
      <item>
        <title>过往的记忆</title>
        <description>&lt;!-- prettier-ignore-start --&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#社交软件&quot; id=&quot;markdown-toc-社交软件&quot;&gt;社交软件&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#小学毕业照&quot; id=&quot;markdown-toc-小学毕业照&quot;&gt;小学毕业照&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#初中毕业照&quot; id=&quot;markdown-toc-初中毕业照&quot;&gt;初中毕业照&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- prettier-ignore-end --&gt;

这篇文字算是一些零碎旧时光记忆的合集吧，没有主题，纯粹是想到什么写什么，零碎记忆拼凑而成，算是给旧时光画一个句号。

&lt;h2 id=&quot;社交软件&quot;&gt;社交软件&lt;/h2&gt;

微信应该是14年左右火起来的，我还是到了第二段职业生涯才开始使用微信，大约是16-18年样子。

早期都是使用 QQ，还记得传美版QQ么，很喜欢那个蓝色星月版本，以及通知的提示音。

记得以前看到一个 QQ 签名，我使用了很久，“此去经年，感叹那两个少年，一个温柔了岁月，一个惊艳了流年···”

&lt;h2 id=&quot;小学毕业照&quot;&gt;小学毕业照&lt;/h2&gt;

&lt;style&gt;
  .image-gallery {
    overflow: auto;
    margin-left: -1% !important;
  }
  .image-gallery li {
    float: left;
    display: block;
    padding:3px 3px;
    width: 19%;
  }
  .image-gallery li a {
    text-align: center;
    text-decoration: none !important;
    color: #777;
  }
  .image-gallery li a span {
    display: block;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    padding: 3px 0;
  }
  .image-gallery li a img {
    width: 100%;
    display: block;
    box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
  }
&lt;/style&gt;

&lt;ul class=&quot;image-gallery&quot;&gt;
  
&lt;/ul&gt;

还有一些小伙伴：

&lt;style&gt;
  .image-gallery {
    overflow: auto;
    margin-left: -1% !important;
  }
  .image-gallery li {
    float: left;
    display: block;
    padding:3px 3px;
    width: 19%;
  }
  .image-gallery li a {
    text-align: center;
    text-decoration: none !important;
    color: #777;
  }
  .image-gallery li a span {
    display: block;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    padding: 3px 0;
  }
  .image-gallery li a img {
    width: 100%;
    display: block;
    box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
  }
&lt;/style&gt;

&lt;ul class=&quot;image-gallery&quot;&gt;
  
  &lt;li&gt;
    &lt;a href=&quot;/images/2000/%E7%A7%A6%E9%A2%96%E8%93%89.jpg&quot; title=&quot;秦颖蓉&quot;&gt;&lt;img src=&quot;//images.weserv.nl/?url=wsdjeg.net/images/2000/%E7%A7%A6%E9%A2%96%E8%93%89.jpg&amp;amp;w=300&amp;amp;h=300&amp;amp;output=jpg&amp;amp;q=50&amp;amp;t=square&quot; alt=&quot;秦颖蓉&quot; title=&quot;秦颖蓉&quot; /&gt;&lt;/a&gt;
  &lt;/li&gt;
  
&lt;/ul&gt;

&lt;h2 id=&quot;初中毕业照&quot;&gt;初中毕业照&lt;/h2&gt;

&lt;style&gt;
  .image-gallery {
    overflow: auto;
    margin-left: -1% !important;
  }
  .image-gallery li {
    float: left;
    display: block;
    padding:3px 3px;
    width: 19%;
  }
  .image-gallery li a {
    text-align: center;
    text-decoration: none !important;
    color: #777;
  }
  .image-gallery li a span {
    display: block;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    padding: 3px 0;
  }
  .image-gallery li a img {
    width: 100%;
    display: block;
    box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
  }
&lt;/style&gt;

&lt;ul class=&quot;image-gallery&quot;&gt;
  
&lt;/ul&gt;

</description>
        <pubDate>Mon, 30 Jun 2003 00:00:00 +0000</pubDate>
        <link>https://wsdjeg.net/memories-of-old-days/</link>
        <guid isPermaLink="true">https://wsdjeg.net/memories-of-old-days/</guid>
        
        
        <category>生活随笔</category>
        
      </item>
    
  </channel>
</rss>
