简介:这是一份面向 Notepad++ 用户的 KamiTheme 配色主题包,适合希望改善默认编辑器视觉体验、长期编码或写文档时减轻眼部疲劳的开发者与文字工作者。压缩包共 2 个文件,包含 1 个 xml 主题定义文件和 1 个 txt 配套说明,整体约 7KB,体积轻巧,便于快速导入、备份与在多台设备间迁移。主题以 KamiTheme 为核心,配合 Consolas 12 号字体的显示效果,对关键字、注释、字符串等语法元素提供统一而柔和的色彩区分,日常查看代码、日志或纯文本时都能保持较清晰的层次感。已有 10300 人学习或下载,说明该配色方案在社区中有一定认可度。对于想低成本替换 Notepad++ 默认主题、追求简洁耐看界面并保留轻量配置的读者,这份资源具有直接的参考和使用价值,也适合作为个人编辑器外观定制的起点。
1. 换 Notepad++ 主题这件事,起因往往不太体面
连着看几个小时默认白底黑字,眼睛发酸,于是在语言格式设置里随手点了个暗色,结果行号栏还是白的、缩进参考线整条消失、当前行高亮像贴了块补丁、选中一段代码反白到看不清字。Notepad++ 主题不是一张壁纸,而是一份被编辑器逐项读取的样式表:它管着每种语言里每一个 token 的前景与背景、字体与粗细,也管着行号栏、光标、选区、折叠栏这些“非代码区域”。想让配色真的顺眼,得先知道每个颜色写在哪、被谁读、什么时候会被覆盖。这篇按“看清楚结构 → 改出一份能用的 → 记住翻车点 → 批量迁移”的顺序走一遍,适合天天泡在编辑器里、愿意花半小时把配色一次性理顺的从业者,也适合只想把别人那套配色安全搬过来的人。
2. 拆开主题 XML:GlobalStyles 和 LexerStyles 各自管哪块屏幕
主题文件本质是一份 XML,根节点NotepadPlus下面并列两块:LexerStyles管代码区,GlobalStyles管界面件。搞不清这两块的边界,改配色就是盲改——你明明把背景调暗了,行号栏却纹丝不动,因为那属于GlobalStyles的地盘。
2.1 主题文件的真实结构与存放位置
一份被 Notepad++ 识别的主题,文件名就是下拉列表里显示的名字,扩展名.xml,存放在用户配置目录的themes子目录下,路径是%APPDATA%\Notepad++\themes。便携版不走这条路,主题目录就在程序自己的themes文件夹里,跟主程序同级。当前生效的那套样式会被写进同级的stylers.xml,界面上的窗口位置、字体缩放等杂项记在config.xml,这三个文件是一组,动主题之前先认清它们的关系。
打开任意一个内置主题,结构长这样(节选,只保留关键节点):
<?xml version="1.0" encoding="UTF-8" ?> <NotepadPlus> <LexerStyles> <LexerType name="c" desc="C" ext=""> <WordsStyle name="DEFAULT" styleID="0" fgColor="D4D4D4" bgColor="1E1E1E" fontName="Consolas" fontStyle="0" fontSize="11" /> <WordsStyle name="COMMENT" styleID="1" fgColor="6A9955" bgColor="1E1E1E" fontName="" fontStyle="2" fontSize="" /> </LexerType> </LexerStyles> <GlobalStyles> <WidgetStyle name="Default Style" styleID="0" fgColor="D4D4D4" bgColor="1E1E1E" fontName="Consolas" fontStyle="0" fontSize="11" /> <WidgetStyle name="Line number margin" styleID="33" fgColor="858585" bgColor="1E1E1E" fontName="Consolas" fontStyle="0" fontSize="10" /> </GlobalStyles> </NotepadPlus>LexerType的name是语言标识(c、cpp、python、xml、sql这些),desc是给人看的描述,ext一般留空由内置映射决定。一个LexerType下挂若干WordsStyle,每条对应这类语言里的一个语法成分。GlobalStyles下挂WidgetStyle,对应的是行号栏、光标、选区这些“不是代码但天天盯着看”的部件。
提示:不要新建空文件从零写起。内置主题里
GlobalStyles的条目最全,先复制一份当底板,比对着补条目省事得多,也少踩“少写一个节点导致某块区域保留旧色”的坑。
2.2 GlobalStyles:被忽略的六个“背景件”
大部分人改主题只改代码区,改完之后屏幕上一半暗一半亮,就是这些背景件没跟上。下表是暗色主题下必须过一遍的条目,名称按内置主题里的写法列,实际文件里条目更多,按需增减:
| WidgetStyle 名称 | 控制对象 | 暗色主题下 |
|---|---|---|
| Default Style | 无专属配色的语言的兜底前景/背景/字体 | 必改 |
| Current line background colour | 光标所在行的底色 | 必改 |
| Selected text colour | 选中区域的底色 | 必改 |
| Caret colour | 光标颜色,填在fgColor上 | 必改 |
| Line number margin | 行号栏的前景、背景、字体 | 必改 |
| Indent guideline style | 缩进参考竖线 | 必改 |
| Brace highlight style | 配对括号高亮 | 建议 |
| Bad brace colour | 括号不匹配提示 | 建议 |
| Edge colour | 长行边界竖线 | 建议 |
| Fold margin | 代码折叠栏背景 | 建议 |
| Smart HighLighting | 双击选中词的同名高亮 | 建议 |
| Find Mark Style | 查找结果标记 | 建议 |
| White space symbol | 空格与制表符的可视符号 | 可选 |
| Bookmark margin | 书签栏 | 可选 |
WidgetStyle的styleID大多数写成0,只有少数几个与编辑器底层预定义样式号对齐,比如行号栏常见33、配对括号高亮34、括号错误35、缩进参考线37。这意味着改WidgetStyle时主要靠name匹配,styleID照抄底板即可,别自作主张去重编号。
Caret colour和Edge colour这类条目只有fgColor没有bgColor,因为它们画的是线条不是填充块。写的时候少一个属性通常不报错,只是不生效,属于“看着对、实际没变”的典型。
2.3 LexerStyles:styleID 才是真正的匹配键
GlobalStyles靠名字匹配,LexerStyles反过来——WordsStyle是按styleID落到对应语言样式槽位上的,name更多是给人读的标签。同一个styleID在不同语言里指向的成分并不一致,C 的 1 号是块注释,某个脚本语言里 1 号可能是别的成分。所以跨语言抄styleID是典型的翻车动作:你把 Python 的注释色抄给 C,结果关键字变成绿色、注释还是白的。
下面这张表是一批常见语言的共性成分,写主题时按name找、按styleID核对,比凭记忆靠谱:
| name(常见写法) | 常见 styleID | 含义 |
|---|---|---|
| DEFAULT | 0 | 普通文本、标识符主体 |
| COMMENT | 1 | 块注释 |
| COMMENT LINE | 2 | 行注释 |
| NUMBER | 3 | 数字字面量 |
| KEYWORDS | 4 | 关键字第一组 |
| STRING | 5 | 字符串 |
| CHARACTER | 6 | 字符字面量 |
| OPERATOR | 7 | 运算符 |
| IDENTIFIER | 8 | 标识符 |
| PREPROCESSOR | 9 | 预处理指令 |
| INSTRUCTION WORD | 10 | 语句关键字 |
| TYPE WORD | 11 | 类型名 |
拿不准的时候最稳的办法是打开底板文件,搜语言名,看它下面的WordsStyle是怎么排的。内置主题的编号是编辑器自己认的,抄它不会错。真要确认某个styleID对应哪类文字,改一个刺眼的颜色(比如纯品红),加载后看屏幕上哪片文字变色,一次就能对上号——这个方法土但准,比对着文档猜快得多。
2.4 四个属性:前景、背景、字体、字号
fgColor和bgColor是六位十六进制,顺序是RRGGBB,FF0000是纯红、0000FF是纯蓝。这里有个高频误解:编辑器底层绘制库习惯用BBGGRR,Notepad++ 在读写主题文件时做了转换,所以你从底层接口或者某些取色工具里拿到的值,直接填进主题会红蓝互换,屏幕上出现诡异的蓝色背景就是这个原因。判断方法很简单,填FF0000看是不是红,是红就说明顺序对。
fontName留空表示继承Default Style的字体,只在需要等宽或需要区分的成分上(注释用斜体、关键字加粗)单独写。fontSize留空同理继承默认值,注意这里的字号影响行高,全局字号改动会让整个编辑区的行距跟着变。
fontStyle是位标志:0常规、1加粗、2斜体、3加粗加斜体。这个字段是最容易被忽略的排版层次来源——一套只有颜色没有字重差异的主题,读起来会平,关键字和普通标识符糊成一片。我的习惯是注释用2(斜体)、关键字用1(加粗)、其余0,三层足够。
3. 做一份能用的暗色主题:从复制内置文件到跑通加载
结构清楚之后就可以动手了。这一章走一遍完整流程:备份、挑底板、改全局层、批量统一语言层、校验加载。每一步都给可执行的命令,跟着敲就行。
3.1 先备份再动手
改主题最怕的是把stylers.xml改坏了,重启之后界面变成一块块黑底黑字,连菜单都看不清。备份只需一条命令,PowerShell 下执行:
$cfg = Join-Path $env:APPDATA 'Notepad++' $dst = Join-Path (Get-Location) ("backup-" + (Get-Date -Format 'yyyyMMdd-HHmm')) New-Item -ItemType Directory -Path $dst | Out-Null Copy-Item "$cfg\themes", "$cfg\stylers.xml", "$cfg\config.xml" -Destination $dst -Recurse Write-Output "备份到 $dst"这段做三件事:拼出配置目录、按时间戳建备份目录、把主题目录和两个配置文件整体复制过去。-Recurse不能省,themes是目录。便携版的用户把$env:APPDATA\Notepad++换成程序目录即可。备份目录建议留在固定位置,别放临时目录,回滚的时候你未必还记得路径。
3.2 挑一个内置主题当底板
不要从空白文件起手。先列出内置主题,挑一个条目最全的暗色主题复制成新文件:
$themeDir = Join-Path $env:APPDATA 'Notepad++\themes' Get-ChildItem $themeDir -Filter *.xml | Select-Object Name, Length | Sort-Object Length -Descending按文件大小排序是有用的:体积大的主题通常覆盖的语言更多、GlobalStyles条目更全,拿它当底板能少补很多节点。选好之后复制并重命名,新文件名就是将来在下拉列表里看到的名字,建议用纯 ASCII、不带空格,省得某些场景下读不到:
Copy-Item "$themeDir\DarkModeDefault.xml" "$themeDir\MyDark.xml"内置主题的具体名单各版本不同,命令跑出来是什么就用什么,别照着记忆里的文件名硬写。
3.3 先改全局层,再改语言层
顺序很重要。先改GlobalStyles,因为它是兜底:Default Style决定没有专属配色的语言长什么样,也决定代码区之外的底色基调。把Default Style的前景背景定下来,再改行号栏、当前行、选区、光标、缩进线这几项,屏幕的“框”就稳了:
<GlobalStyles> <WidgetStyle name="Default Style" styleID="0" fgColor="D4D4D4" bgColor="1E1E1E" fontName="Consolas" fontStyle="0" fontSize="11" /> <WidgetStyle name="Current line background colour" styleID="0" bgColor="2A2A2A" /> <WidgetStyle name="Selected text colour" styleID="0" bgColor="264F78" /> <WidgetStyle name="Caret colour" styleID="0" fgColor="AEAFAD" /> <WidgetStyle name="Line number margin" styleID="33" fgColor="858585" bgColor="1E1E1E" fontName="Consolas" fontStyle="0" fontSize="10" /> <WidgetStyle name="Indent guideline style" styleID="37" fgColor="404040" bgColor="1E1E1E" /> <WidgetStyle name="Brace highlight style" styleID="34" fgColor="FFD700" bgColor="1E1E1E" fontStyle="1" /> <WidgetStyle name="Bad brace colour" styleID="35" fgColor="FF5370" bgColor="1E1E1E" /> <WidgetStyle name="Edge colour" styleID="0" fgColor="404040" /> </GlobalStyles>几个取值有讲究。Current line background colour只比主背景亮一点点(1E1E1E对2A2A2A),差太多会变成一条横贯屏幕的亮带,注意力全被吸走。Selected text colour用偏冷的蓝灰,选中一片代码时和暖色的关键字不打架。Indent guideline style一定要比背景亮一档但明显暗于正文,404040这种就够,太亮会让整屏布满竖线。Caret colour建议取一个比正文稍暗的中性灰,纯白光标在暗底上太跳。
3.4 用脚本批量统一语言层的背景
底板里几十个语言,逐个手改背景不现实。写个脚本把所有bgColor刷成同一个值,再单独把少数需要层次差的条目捞出来覆盖:
import sys from pathlib import Path from xml.etree import ElementTree as ET src, dst = Path(sys.argv[1]), Path(sys.argv[2]) BG, FG, FONT = "1E1E1E", "D4D4D4", "Consolas" tree = ET.parse(src) root = tree.getroot() for el in root.iter(): if el.get("bgColor"): el.set("bgColor", BG) # 代码区、行号栏、折叠栏统一底色 for ws in root.iter("WidgetStyle"): name = ws.get("name", "") if name == "Current line background colour": ws.set("bgColor", "2A2A2A") # 当前行单独留层次 elif name == "Selected text colour": ws.set("bgColor", "264F78") # 选区用蓝灰,和暖色高亮分开 elif name == "Default Style": ws.set("fgColor", FG) ws.set("fontName", FONT) tree.write(dst, encoding="UTF-8", xml_declaration=True) print(f"已写出 {dst}")脚本逻辑很直白:第一轮无差别刷背景,第二轮按WidgetStyle的name把需要保留层次的三个条目改回去。BG、FG、FONT三个常量就是你要换的目标配色,改这三行即可。注意el.get("bgColor")判空很重要,只有fgColor的条目(比如Caret colour)不能被写入背景,否则会多出一个不属于它的属性。tree.write输出的是标准 XML,自闭合标签会被规范化,注释可能丢失,这对主题文件没影响,但如果你的底板里有手写注释想保留,就别用这个脚本全部重写,改成逐行正则替换。
3.5 校验并加载
写完之后先做语法校验,XML 坏一个标签,编辑器会静默退回默认主题,你会以为改动没生效:
$f = Join-Path $env:APPDATA 'Notepad++\themes\MyDark.xml' try { [xml]$x = Get-Content $f -Raw "语言数: " + $x.NotepadPlus.LexerStyles.LexerType.Count "全局样式数: " + $x.NotepadPlus.GlobalStyles.WidgetStyle.Count } catch { "XML 解析失败: " + $_.Exception.Message }两个计数正常输出,说明文件结构没问题。然后在编辑器里打开“设置 → 语言格式设置”,主题下拉里选中新文件,点“保存并关闭”。这一步不能省——只有点了保存,当前样式才会写回stylers.xml,否则关掉编辑器一切照旧。
4. 暗色主题的六处翻车点:现象、原因与回滚手段
下面这些是改主题时反复出现的实际问题,按“看到什么 → 为什么 → 怎么办”写,遇到对得上的直接照做。
4.1 行号栏白得刺眼,代码区却是暗的
现象:代码区已经是深灰底,左侧行号栏仍然一片白,滚动时特别突兀。
原因:只改了LexerStyles里的DEFAULT,没动GlobalStyles的Line number margin。代码区和行号栏是两套绘制逻辑,前者归语言样式,后者归WidgetStyle。
解决:在GlobalStyles里补Line number margin,同时把fontName、fontSize写上,否则行号和代码的字号可能对不齐。改完在语言格式设置里点保存,不要直接关窗口。
4.2 从别处抄来的配色,红蓝互换
现象:明明填的是深灰底配橙红关键字,加载后背景发蓝、注释发黄,色相整个错位。
原因:颜色字节序问题。Notepad++ 主题文件用RRGGBB,而底层绘制接口和一些取色工具输出BBGGRR,直接粘贴就相当于把红蓝通道交换了一次。
解决:拿FF0000做一次探针测试,显示红色说明顺序正确。已经写错的文件,用脚本把每对字节前后互换回来就行,但更省事的做法是从 Notepad++ 自己的主题文件里取色,别从别处搬十六进制值。
4.3 某些语言还是白底,只有少数几种变暗
现象:C、Python 都正常,切到某个不常用的语言,整个编辑区又变回亮色。
原因:底板主题里没有这个语言的LexerType节点,编辑器退回Default Style或其他兜底配色。这在跨版本使用旧主题时特别常见,新版本增加了语言,老主题文件里自然没有。
解决:从当前版本的内置主题里把缺失的LexerType整段复制过来,再用批量脚本刷一遍背景。判断缺哪些语言的办法是把主题文件和内置主题的LexerType名字列表做差集,几十行 Python 就能列全,比一个个切换语言试快得多。
4.4 改了文件没生效,重启后还是旧配色
现象:编辑主题文件保存了,重启编辑器毫无变化,甚至自己改的内容消失了。
原因:编辑器运行期间以内存中的配置为准,退出时会用自己的状态覆盖stylers.xml。如果你在编辑器开着的时候改文件,退出时就被覆盖了。另外主题名和文件名不一致、文件放在错误的目录,也会导致下拉列表里根本看不到新主题。
解决:改文件前先完全退出编辑器,改完再启动,然后走一遍“语言格式设置 → 选主题 → 保存并关闭”。便携版和安装版的目录不同,确认一下themes到底在%APPDATA%还是程序目录下。
4.5 自己重编了 styleID,注释色跑到关键字上
现象:本来只想统一一下编号,结果注释变成关键字色,字符串跑到运算符上。
原因:WordsStyle是按styleID落到样式槽位的,编号一改,颜色就跟着挪了位置。name只是标签,改它不影响显示,改styleID影响。
解决:styleID一律照抄内置底板,不重编。要调整只改颜色和字体字段。已经改乱的,从备份里把原始文件取回来重做,别试图逆向修。
注意:回滚比修复便宜。每改一版就复制一份带日期的主题文件,出问题直接切回上一版,比对着 XML 逐行找错快得多。
5. 配色迁移与批量改造:把十六进制表喂给脚本
前面都是单文件内改,实际更常见的需求是:手上有一套别处看中的配色(十六进制色板、别的编辑器的主题文件、设计稿里的色值),想搬到 Notepad++ 里。这一章讲迁移路径和自动校验。
5.1 建立一份配色映射表
迁移的第一步不是写代码,是把源配色拆成语义角色:背景、正文、注释、关键字、字符串、数字、类型名、运算符、选中、当前行。角色定下来,再去WordsStyle里找对应的name。下面是一份从外部色板迁移时的典型映射,左边是你的角色,右边是主题里要改的条目:
| 语义角色 | 目标条目 | 建议对比度 |
|---|---|---|
| 主背景 | 所有bgColor+Default Style | 与正文 ≥ 7:1 |
| 正文 | DEFAULT的fgColor | ≥ 7:1 |
| 注释 | COMMENT、COMMENT LINE | 3:1 ~ 4.5:1 |
| 关键字 | KEYWORDS、INSTRUCTION WORD | ≥ 4.5:1 |
| 字符串 | STRING、CHARACTER | ≥ 4.5:1 |
| 数字 | NUMBER | ≥ 4.5:1 |
| 当前行 | Current line background colour | 与主背景差 8 ~ 12 级亮度 |
| 选区 | Selected text colour | 选中文字仍可读 |
注释的对比度刻意压低是合理的:它应该是背景信息,不该比代码更抢眼。但别低到 2:1 以下,暗色主题下深绿注释糊进黑底是最常见的可读性事故。
5.2 按角色批量写入
有了映射表,脚本就简单了:按name匹配WordsStyle,把颜色填进去。注意同一个name会在几十种语言里重复出现,遍历全树一次改完:
import sys from pathlib import Path from xml.etree import ElementTree as ET ROLE = { "DEFAULT": ("D4D4D4", None, "0"), "COMMENT": ("6A9955", None, "2"), "COMMENT LINE": ("6A9955", None, "2"), "NUMBER": ("B5CEA8", None, "0"), "KEYWORDS": ("569CD6", None, "1"), "INSTRUCTION WORD": ("C586C0", None, "1"), "TYPE WORD": ("4EC9B0", None, "0"), "STRING": ("CE9178", None, "0"), "CHARACTER": ("CE9178", None, "0"), "OPERATOR": ("D4D4D4", None, "0"), } src, dst = Path(sys.argv[1]), Path(sys.argv[2]) tree = ET.parse(src) root = tree.getroot() hit = 0 for ws in root.iter("WordsStyle"): role = ROLE.get(ws.get("name", "")) if not role: continue fg, bg, style = role ws.set("fgColor", fg) if bg: ws.set("bgColor", bg) ws.set("fontStyle", style) hit += 1 tree.write(dst, encoding="UTF-8", xml_declaration=True) print(f"命中 {hit} 条样式")ROLE字典的键是主题里的name,值依次是前景、背景、字重。背景统一留None是因为前一步已经把全局背景刷平了,这里只改前景和字重就够了,避免把某些特殊槽位(比如 diff 视图的增删色)也刷成同一个背景。hit计数用来确认脚本真的改到了东西——命中数为 0 基本只有一种可能:name写法和文件里不一致,大小写或空格有差异,打开文件搜一下就知道。
5.3 用对比度脚本做一次体检
颜色好不好看很主观,可读性却是可以量化的。下面这段按 WCAG 的相对亮度公式,扫一遍主题里所有前景背景组合,把对比度低于阈值的列出来:
import sys from xml.etree import ElementTree as ET def lum(h): r, g, b = (int(h[i:i+2], 16) / 255 for i in (0, 2, 4)) f = lambda c: c / 12.92 if c <= 0.03928 else ((c + 0.055) / 1.055) ** 2.4 return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b) def ratio(a, b): la, lb = lum(a), lum(b) hi, lo = max(la, lb), min(la, lb) return (hi + 0.05) / (lo + 0.05) root = ET.parse(sys.argv[1]).getroot() default_bg = "1E1E1E" bad = [] for ws in root.iter("WordsStyle"): fg = ws.get("fgColor") or "" bg = ws.get("bgColor") or default_bg if len(fg) != 6 or len(bg) != 6: continue c = ratio(fg, bg) if c < 3.0: bad.append((round(c, 2), ws.get("name"), fg, bg)) bad.sort() for c, name, fg, bg in bad[:20]: print(f"{c:>5} {name:<20} {fg} on {bg}") print(f"低于 3:1 的样式共 {len(bad)} 条")lum把十六进制转成相对亮度,ratio套对比度公式。阈值定在 3.0 是因为低于这个值基本就是“看着有色、读着费劲”。输出按对比度升序,排在前面的就是最该调的。默认背景写死成主背景的色值,如果你的主题里各语言背景不统一,把default_bg改成按LexerType动态取。这个脚本我一般在新主题成型后跑一次,改配色时再跑一次,比肉眼盯屏幕靠谱。
6. 主题切换的回滚位:config.xml 与进程时序
主题做到能用了,还剩一个日常问题:白天用浅色、晚上用深色,每次都要开设置点两下。想省这一步,就得动config.xml里记录当前主题名的那项配置。稳妥的做法不是记住节点全名(不同版本写法有差异),而是先搜:关掉编辑器,用文本方式打开config.xml,搜你当前主题的名字,命中的那行把值换成新主题的文件名(含.xml),保存即可。切换前先确认进程已退出,否则退出时会被内存里的旧值覆盖回去。
写成脚本就是先查进程再改文件:
$cfg = Join-Path $env:APPDATA 'Notepad++\config.xml' $theme = 'MyDark.xml' if (Get-Process -Name notepad++ -ErrorAction SilentlyContinue) { Write-Output "编辑器还在运行,先退出再切" exit 1 } $content = Get-Content $cfg -Raw -Encoding UTF8 $content = $content -replace '(?<=<GUIConfig name="StylerTheme">)[^<]+', $theme Set-Content $cfg -Value $content -Encoding UTF8 -NoNewline Write-Output "已切换为 $theme"Get-Process那段是后悔药:编辑器运行中改配置,退出时必被覆盖,脚本等于白跑,所以要提前拦住。正则用后行断言只替换节点内的文本,不动其他配置。-NoNewline保证文件尾不多出一个空行。这套脚本配合两份主题文件,就能做到“关编辑器 → 跑脚本 → 启动”的固定动作,也可以再包一层快捷方式。
从那以后我每次改主题,都强制走一遍“先备份themes和stylers.xml→ 完全退出编辑器 → 改文件 → 用 XML 校验确认结构 → 打开后保存并关闭”的流程,一次没落下。血泪经验就是省掉哪一步,哪一步就会在第二天变成一屏看不清的代码。希望帮到你。
本文还有配套的精品资源,点击获取