我给自己写了一个本地代码片段管理器:秒搜、不上传、UI 全自定义实录
目录
- 缘起:为什么我总是找不到那段代码
- 需求拆解:从"能存片段"到"能秒搜"
- 技术选型:一个 HTML 文件 + 一个 JSON 就够了
- 核心实现一:片段存储与语法高亮
- 核心实现二:模糊搜索与标签过滤
- UI 定制:片段管理器也是"自己的工具箱"
- 三个让我卡了一阵的坑
- 结尾:开发者工具的"随取随用"哲学
1. 缘起:为什么我总是找不到那段代码
我写代码十几年,有些片段用过几十次却还是记不住:
- 那个"防抖函数"的精确写法;
- 那段"Git 一次拆分提交"的命令序列;
- 那个"正则提取中文字符"的 pattern。
它们散落在聊天记录、备忘录、旧项目里,每次要用都要重新搜、重新写、重新调试。我也试过 snippet 工具,但:
- 云端方案要登录、要同步、要担心哪天收费策略变了;
- IDE 插件方案绑死在某个编辑器,换 IDE 就丢;
- 搜索难用,要么只搜标题、要么不支持中文、要么按文件夹翻。
我忽然意识到:代码片段是开发者最私人的资产,凭什么要交给云端、绑给某个 IDE。既然现成工具都不顺手,那就自己写一个。
2. 需求拆解:从"能存片段"到"能秒搜"
把"做一个片段管理器"拆成可验收清单:
| 诉求(人话) | 拆解后(可验收) |
|---|---|
| 能存 | 标题 + 代码 + 语言 + 标签,本地持久化 |
| 能搜 | 标题/正文/标签模糊搜索,毫秒级返回 |
| 能复制 | 一键复制到剪贴板,带"已复制"反馈 |
| 能分类 | 按语言、按标签筛选,侧栏可见 |
| 能编辑 | 选中即编辑,保存即写回 |
| 不上传 | 全程本地,导出/导入 JSON 备份 |
这张表决定了工具的骨架。功能不多,但每一项都做到位——这是我对所有"自己用的工具"的一贯要求。
3. 技术选型:一个 HTML 文件 + 一个 JSON 就够了
我犹豫过要不要上 SQLite,但仔细想需求——几百到几千条片段,纯文本,结构简单,localStorage 或一个 JSON 文件完全够用:
| 能力 | 方案 |
|---|---|
| 存储 | localStorage(小规模)或 File System Access API 写 JSON |
| 语法高亮 | highlight.js 或 Prism |
| 搜索 | 自建内存索引 + 模糊匹配 |
| 复制 | navigator.clipboard.writeText |
| 编辑 | contenteditable 或轻量 CodeMirror |
整个工具就是一个 HTML 文件,双击就能开。没有安装包、没有更新提示、没有后台进程——片段库就是一个 JSON,换机器复制走即可。
心得:选型时先问"我到底需要什么"。本地小工具的最高境界是双击即用、关掉即走。
4. 核心实现一:片段存储与语法高亮
片段数据结构很简单:
const snippet = {
id: crypto.randomUUID(),
title: '防抖函数',
code: 'function debounce(fn, delay) { ... }',
lang: 'javascript',
tags: ['utils', '性能'],
updatedAt: Date.now(),
};
语法高亮用 highlight.js,一行调用:
const highlighted = hljs.highlight(snippet.code, {
language: snippet.lang
}).value;
container.innerHTML = `<pre><code class="hljs">${highlighted}</code></pre>`;
几个让体验"顺手"的细节:
- 语言自动识别。新建片段时不选语言也能高亮——
hljs.highlightAuto(code)兜底; - 复制按钮在每段右上角。鼠标移入显现,不占常驻空间;
- Tab 键保留缩进。编辑代码片段时 Tab 不切焦点,而是插入空格——这是代码编辑器的基本素养。
心得:片段管理器的核心指标是"从想用到贴出来不超过 3 秒"。任何多余点击都是摩擦。
5. 核心实现二:模糊搜索与标签过滤
搜索是这类工具的灵魂。我实现了一个轻量模糊匹配——子序列匹配 + 连续匹配加分:
function fuzzyScore(text, query) {
let qi = 0, score = 0, consecutive = 0;
for (let i = 0; i < text.length && qi < query.length; i++) {
if (text[i].toLowerCase() === query[qi].toLowerCase()) {
score += 1 + consecutive++; // 连续匹配加分
qi++;
} else {
consecutive = 0;
}
}
return qi === query.length ? score : -1; // 全部命中才算
}
搜索时对标题、正文、标签都算分,取最高:
function search(query) {
return snippets
.map(s => ({
s,
score: Math.max(
fuzzyScore(s.title, query) * 3, // 标题权重高
fuzzyScore(s.code, query),
Math.max(...s.tags.map(t => fuzzyScore(t, query) * 2)),
),
}))
.filter(r => r.score >= 0)
.sort((a, b) => b.score - a.score)
.map(r => r.s);
}
几个让搜索"好用"的细节:
- 标题命中权重最高,标签次之,正文最低——符合直觉;
- 空 query 显示全部,按更新时间倒序——日常打开就是最近用的;
- 搜索结果即时显示,输入即过滤,不需要回车。
心得:搜索体验的好坏,不在"能不能搜到",而在"输入第一个字就有反馈"。即时性比精确性更影响手感。
6. UI 定制:片段管理器也是"自己的工具箱"
本地工具最大的特权,是 UI 完全我说了算。我给自己定了几个商业软件不会这么做的设计选择:
- 左栏标签 + 右栏列表/详情。标签作为主入口,比文件夹更贴合"按用途找"的习惯;
- 搜索框常驻顶部。打开就能搜,不藏在菜单里;
- 暗色为主,跟随系统。长时间看代码,暗色更护眼;
- 列表项显示语言徽章。一眼区分 JS/Python/Shell,不必点进去看。
这些设计在商业产品里几乎不可能出现——它们太"个人化"了。但本地工具的意义,恰恰就是让软件贴合你的查找习惯,而不是让你迁就软件的功能预设。
7. 三个让我卡了一阵的坑
坑一:localStorage 容量限制。 几千条片段 + 代码正文,可能逼近 5MB 上限。解决办法是检测容量,超限自动切换到 File System Access API 写 JSON 文件。教训:本地存储方案要预留"长大了怎么办"的退路。
坑二:语法高亮拖慢渲染。 几百条片段同时高亮会卡。改成只高亮可视区域 + 滚动时按需高亮后丝滑。教训:任何"列表 + 重计算"的场景,虚拟滚动都是必选项。
坑三:复制按钮在 HTTPS 之外失效。 navigator.clipboard 在 file:// 协议下部分浏览器不支持。兜底用 document.execCommand('copy') + 临时 textarea,虽然 API 已废弃但 file:// 下仍是最稳的。
8. 结尾:开发者工具的"随取随用"哲学
做完这个片段管理器,我对"开发者工具"有了一种更深的体会:
- 它不抢你注意力。没有推荐片段、没有"热门分享"、没有社区排行;
- 它尊重你的代码。片段在本地 JSON 里,不发起任何网络请求;
- 它尊重你的时间。打开即搜、搜到即贴,三秒完事。
在这个所有软件都在抢用户时长的时代,一个"打开就找、找到即用、用完即走"的本地工具,反而成了一种奢侈。
如果你也有一堆散落的代码片段、也想要一个"秒搜即贴"的管理器,我强烈建议自己写一个。技术门槛比想象中低,一个 HTML 文件就够;真正难的是克制住加功能的冲动——不做社区、不做分享、不做"AI 自动补全",就做一个老老实实的本地片段库。
工具小而静,价值往往不在多,而在"它永远在那里,三秒就能取到"。
- 点赞
- 收藏
- 关注作者
评论(0)