npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

caolang

v0.1.0

Published

草语言 — A meme-based Chinese programming language

Readme

草语言 (CaoLang) 🌿

一个基于梗的中文编程语言。写代码?不,我们叫它「整活」。

草语言是一门用中文互联网黑话作为关键字的编程语言。变量声明叫搞个,函数定义叫整活,返回值叫栓Q,循环叫,跳出循环叫

如果你觉得 JavaScript 的 undefined is not a function 不够有灵魂,试试草语言的 这谁啊,不认识

整活 斐波那契(n)「
  如果(n <= 1)「
    栓Q n
  」
  栓Q 斐波那契(n - 1) + 斐波那契(n - 2)
」

搞个 i = 0
卷(i < 10)「
  喊话(斐波那契(i))
  i = i + 1
」

安装 Installation

# 用 npm 安装
npm install -g caolang

# 或者直接 npx 一把梭
npx caolang run hello.cao

从源码运行 Run from Source

git clone <repo-url>
cd caolang
npm install
npm run dev -- run examples/hello.cao

用法 Usage

cao run <文件.cao>        # 运行一个 .cao 文件
cao                       # 启动交互式控制台(REPL)
cao repl                  # 同上
cao tokenize <文件.cao>   # 查看词法分析结果(给卷王看的)
cao parse <文件.cao>      # 查看语法树(给更卷的卷王看的)
cao --help                # 显示帮助
cao --version             # 显示版本

REPL 长这样:

草语言 (CaoLang) v0.1.0 — 交互式控制台
输入代码开始整活,输入 .exit 退出

草> 喊话("你好世界")
你好世界
草> 1 + 1
2
草> 搞个 x = 42
草> x * 2
84

语言教程 Language Guide

变量:搞个

搞个 名字 = "张三"
搞个 年龄 = 25
搞个 是学生 = 确实
搞个 钱包 = 虚无        // 没钱,虚无

函数:整活

整活 加法(a,b)「
  栓Q a + b
」

喊话(加法(3,4))  // 输出: 7

栓Q 就是 return。为什么叫栓Q?因为感谢这个函数给了我一个返回值,栓Q🙏

条件:如果 / 啊这

如果(年龄 >= 18)「
  喊话("成年了,可以整活了")
」啊这「
  喊话("啊这,还没成年")
」

支持 else if 链:

如果(分数 >= 90)「
  喊话("优秀")
」啊这 如果(分数 >= 60)「
  喊话("及格")
」啊这「
  喊话("寄")
」

循环:卷

搞个 i = 0
卷(i < 10)「
  喊话(i)
  i = i + 1
」

卷不动了?用 跳出循环。想跳过这次继续卷?用 继续卷

搞个 i = 0
卷(确实)「
  如果(i == 5)「润」   // 润了,不卷了
  如果(i == 3)「
    i = i + 1
    继续卷                // 跳过这次,继续卷
  」
  喊话(i)
  i = i + 1
」

布尔值:确实 / 没有内味

搞个 真的 = 确实           // true
搞个 假的 = 没有内味        // false(对,就是这么长,惩罚你写烂逻辑)

逻辑运算:

确实 并且 确实        // 确实
确实 或者 没有内味    // 确实
非 确实              // 没有内味

为什么 没有内味 这么长? 这是 feature 不是 bug。写太多布尔判断说明你代码有问题,长一点让你反思一下。

错误处理:真香 / 草

真香「
  寄("出大事了兄弟!")
」草(那个错误)「
  喊话("草!" + 那个错误)
」

不想处理错误?纯摆烂模式——catch 不接参数:

真香「
  寄("这个错误没人管")
」草「
  摆烂   // 错误?什么错误?我不知道
」

数组

搞个 水果 = ["苹果","香蕉","橘子"]
喊话(水果[0])          // 苹果
推入(水果,"西瓜")      // push
搞个 最后 = 弹出(水果)  // pop
喊话(长度(水果))       // 3

闭包

整活 制造计数器()「
  搞个 计数 = 0
  整活 增加()「
    计数 = 计数 + 1
    栓Q 计数
  」
  栓Q 增加
」

搞个 计数器 = 制造计数器()
喊话(计数器())  // 1
喊话(计数器())  // 2
喊话(计数器())  // 3

摆烂

有时候你就是不想写逻辑。摆烂 是草语言的 no-op / pass:

如果(今天是周一)「
  摆烂   // 周一不想干活
」

标点符号 Punctuation

草语言支持中文标点和 ASCII 标点,可以混用

| 中文 | ASCII | 用途 | |------|-------|------| | 「」『』 | {} | 代码块 | | () | () | 分组 / 函数调用 | | | , | 分隔符 | | | ; | 语句终止符(可选) |

分号完全可选。草语言不需要分号,因为生活已经够累了。


内置函数 Built-ins

| 函数 | 用途 | 示例 | |------|------|------| | 喊话(...) | 打印输出 | 喊话("你好") | | 类型(值) | 返回类型名 | 类型(42)"数字" | | 长度(值) | 字符串/数组长度 | 长度("你好")2 | | 数字化(字符串) | 字符串转数字 | 数字化("42")42 | | 字符串化(值) | 任意值转字符串 | 字符串化(42)"42" | | 推入(数组,值) | 数组末尾添加 | 推入(arr,1) | | 弹出(数组) | 数组末尾弹出 | 弹出(arr) | | 切片(值,开始,结束) | 切片 | 切片("你好世界",0,2)"你好" | | 随机() | 随机数 [0, 1) | 随机() | | 时间戳() | 当前毫秒时间戳 | 时间戳() |


梗味错误信息 Meme Error Messages

草语言的报错不说人话(但说的都是实话):

| 场景 | 报错 | |------|------| | 语法错误 | 啊?这写的什么玩意儿 | | 变量未定义 | 这谁啊,不认识: xxx | | 类型错误 | 类型不对啊兄弟,别乱搞 | | 除以零 | 除以零?脑子瓦特了? | | 栈溢出 | 卷太狠了,栈都溢出了 | | 参数数量错误 | 参数数量不对,搞什么飞机 | | 数组越界 | 越界了兄弟,别越线 | | 字符串没闭合 | 字符串没写完就跑了,引号呢? |


🥚 彩蛋 Easter Eggs

社会信用系统 Social Credit System

cao run your-file.cao --social-credit

如果一个函数里 栓Q(return)超过 5 次,编译器会警告你「太客气了」:

⚠️ 社会信用警告:函数「太客气了」里栓Q了8次,你也太客气了吧!

996 模式

cao run your-file.cao --996

如果你在晚上 9 点到早上 6 点之间跑代码,(while)循环每次迭代有 1% 概率猝死

💀 猝死!你卷到猝死了!回去睡觉!
(996模式:深夜写代码有1%概率猝死)

严厉模式 Strict Mode

在文件开头写 严厉,或者用 --strict 标志:

严厉

喊话("你好")   // 用了ASCII括号,会被教育
🔴 文化自信!请使用中文标点!
第3行:发现 '(',请使用()!
第3行:发现 ')',请使用()!

全部彩蛋

cao run your-file.cao --全部彩蛋

关键字速查表 Keyword Cheat Sheet

搞个    → let / var          (搞一个变量)
整活    → function           (开始整活)
栓Q    → return             (栓Q,谢谢)
喊话    → print              (大声喊话)
如果    → if                 (如果的话...)
啊这    → else               (啊这...)
卷      → while              (开始卷)
润      → break              (润了)
继续卷  → continue           (继续卷!)
摆烂    → pass / no-op       (摆烂了)
寄      → throw              (寄了)
真香    → try                (真香定律)
草      → catch              (草!)
确实    → true               (确实)
没有内味 → false              (没有内味了)
虚无    → null               (虚无)
并且    → and                (并且)
或者    → or                 (或者)
非      → not                (非)

示例程序 Examples

examples/ 目录下有这些示例:

  • hello.cao — 你好世界
  • fibonacci.cao — 斐波那契数列(递归)
  • fizzbuzz.cao — 经典 FizzBuzz(草Buzz)
  • closures.cao — 闭包和计数器
  • error-handling.cao — 真香/草 错误处理
  • meme-showcase.cao — 完整特性展示
  • social-credit.cao — 社会信用系统彩蛋演示

运行示例:

npm run dev -- run examples/meme-showcase.cao

技术细节 Technical Details

  • 实现语言: TypeScript
  • 执行模型: Tree-walking 解释器
  • 解析器: Pratt parser(自顶向下运算符优先级)
  • 作用域: 词法作用域,支持闭包
  • 类型系统: 动态类型(数字、字符串、布尔、虚无、数组、函数)
  • 运行时依赖: 零(纯 TypeScript,无第三方依赖)
  • Unicode: 正确处理 CJK 字符,支持中文标识符
  • 标点: 中文标点在词法分析阶段归一化,解析器只看规范形式

空格无关的关键字识别

草语言使用贪心前缀匹配来识别关键字。你可以写 搞个东西 而不需要空格——词法分析器会自动拆分成 搞个(关键字) + 东西(标识符)。因为中文本来就不用空格。


开发 Development

npm install          # 安装依赖
npm test             # 跑测试(97个)
npm run dev          # 用 tsx 直接跑
npm run build        # 编译到 dist/
npm run lint         # 类型检查

License

MIT