[{"data":1,"prerenderedAt":545},["ShallowReactive",2],{"/2026/terminal-shortcuts":3,"surround-/2026/terminal-shortcuts":539},{"id":4,"title":5,"body":6,"categories":513,"comment":515,"date":516,"description":517,"donation":515,"draft":518,"extension":519,"image":520,"meta":521,"navigation":515,"path":523,"permalink":520,"postfooter":515,"published":520,"readingTime":524,"recommend":520,"references":520,"seo":529,"sitemap":530,"stem":531,"tags":532,"type":537,"updated":516,"__hash__":538},"content/posts/2026/terminal-shortcuts.md","终端快捷命令",{"type":7,"value":8,"toc":496},"minimark",[9,27,38,42,49,97,100,110,121,129,132,138,148,154,162,178,181,184,194,202,225,231,237,248,253,259,265,271,274,281,287,294,315,319,332,340,345,351,365,374,385,400,403,413,431,434,440,446,449,471,475,480,486,490],[10,11,14],"alert",{"title":12,"type":13},"环境","info",[15,16,17,18,22,23,26],"p",{},"macOS + zsh 5.9 + Homebrew 的 ",[19,20,21],"code",{"code":21},"mysql-client","。Linux 上除了 ",[19,24,25],{"code":25},"UseKeychain","（macOS 钥匙串专有）之外都能用。",[15,28,29,30,33,34,37],{},"敲 ",[19,31,32],{"code":32},"shop-test"," 就连上测试库，敲 ",[19,35,36],{"code":36},"aliyun-01"," 就登服务器。",[39,40,41],"h2",{"id":41},"两张表怎么分",[15,43,44,45],{},"判据一句话：",[46,47,48],"strong",{},"要不要拼参数、要不要存密码？",[50,51,52,67],"table",{},[53,54,55],"thead",{},[56,57,58,61,64],"tr",{},[59,60],"th",{},[59,62,63],{},"用哪张表",[59,65,66],{},"例子",[68,69,70,84],"tbody",{},[56,71,72,76,81],{},[73,74,75],"td",{},"要拼参数、要存密码",[73,77,78],{},[19,79,80],{"code":80},"db/connections.conf",[73,82,83],{},"MySQL、Redis",[56,85,86,89,94],{},[73,87,88],{},"命令现成，只是长",[73,90,91],{},[19,92,93],{"code":93},"shortcuts.conf",[73,95,96],{},"ssh、端口转发、kubectl context",[39,98,99],{"id":99},"目录结构",[101,102,108],"pre",{"className":103,"code":105,"language":106,"meta":107},[104],"language-sh","~/.zshrc                          # 只是个 loader，按序 source rc.d/*.zsh\n~/.config/zsh/\n├── rc.d/\n│   ├── 00-path.zsh               # PATH\n│   ├── 10-completion.zsh         # 补全系统\n│   ├── 20-plugins.zsh            # autosuggestions / syntax-highlighting\n│   ├── 30-prompt.zsh             # starship\n│   ├── 40-aliases.zsh            # 通用别名 ll / la\n│   ├── 50-db.zsh                 # 读注册表 → 生成连接别名 + db 命令\n│   ├── 55-shortcuts.zsh          # 读快捷表 → 生成短名 + sc 命令\n│   ├── 60-integrations.zsh       # 终端集成\n│   └── 99-local.zsh              # 本机私有，gitignore\n├── db/connections.conf           # 数据库注册表（无密码，可入库）\n└── shortcuts.conf                # 短名 → 命令\n~/.ssh/config + conf.d/*.conf     # 主机细节：IP / 密钥 / 跳板机\n~/.mylogin.cnf                    # 密码，600，绝不入库\n","sh","",[19,109,105],{"__ignoreMap":107},[15,111,112,113,116,117,120],{},"加一类配置就加一个分片文件，不往 ",[19,114,115],{"code":115},".zshrc"," 里堆。",[19,118,119],{"code":119},"~/.zshrc"," 全文就这几行：",[101,122,127],{"className":123,"code":125,"language":126,"meta":107},[124],"language-zsh","export ZSH_CONFIG_DIR=\"${XDG_CONFIG_HOME:-$HOME/.config}/zsh\"\n\nfor _rc in \"$ZSH_CONFIG_DIR\"/rc.d/*.zsh(N.on); do\n    source \"$_rc\"\ndone\nunset _rc\n","zsh",[19,128,125],{"__ignoreMap":107},[39,130,131],{"id":131},"命令速查",[101,133,136],{"className":134,"code":135,"language":106,"meta":107},[104],"# 数据库\ndb ls                      # 列表，COMMAND 列就是能直接敲的命令\ndb show \u003Cname>             # 明细（不含密码）\ndb auth \u003Cname>             # 录入密码，交互输入\ndb forget \u003Cname>           # 删除本机密码\ndb q \u003Cname> \"select 1\"     # 跑一条 SQL，表格输出，不进交互\n\u003Cname>                     # 直接连，等价于 db connect \u003Cname>\n\n# 其他命令\nsc ls                      # 列表 + 生效状态\nsc show \u003C短名>              # 看展开成什么\nsc edit                    # 编辑快捷表\nsc reload                  # 重载 shell\n",[19,137,135],{"__ignoreMap":107},[15,139,140,143,144,147],{},[19,141,142],{"code":142},"db"," 和 ",[19,145,146],{"code":146},"sc"," 都带 Tab 补全。",[15,149,150,153],{},[19,151,152],{"code":152},"db ls"," 的样子：",[101,155,160],{"className":156,"code":158,"language":159,"meta":107},[157],"language-text","NAME       COMMAND    HOST                     PORT  USER    DATABASE  ENV   AUTH\nshop-test  shop-test  db-test.internal.example 3306  app_ro  app_test  test  ✔\n","text",[19,161,158],{"__ignoreMap":107},[15,163,164,167,168,143,170,173,174,177],{},[19,165,166],{"code":166},"AUTH"," 是本机有没有存密码。每个连接生成两个别名，",[19,169,32],{"code":32},[19,171,172],{"code":172},"mysql-shop-test","，效果一样，后者方便 ",[19,175,176],{"code":176},"mysql-"," + Tab 找同类。",[39,179,180],{"id":180},"加一个数据库",[15,182,183],{},"三步。",[15,185,186,189,190,193],{},[46,187,188],{},"1. 登记连接","，",[19,191,192],{"code":192},"db edit"," 打开注册表，加一行：",[101,195,200],{"className":196,"code":198,"language":199,"meta":107},[197],"language-ini","# name       engine  host                      port  user    database  env\nshop-test    mysql   db-test.internal.example  3306  app_ro  app_test  test\n","ini",[19,201,198],{"__ignoreMap":107},[15,203,204,205,208,209,212,213,216,217,220,221,224],{},"字段之间空格分隔，",[19,206,207],{"code":207},"database"," 不需要就填 ",[19,210,211],{"code":211},"-","。",[19,214,215],{"code":215},"env"," 填 ",[19,218,219],{"code":219},"prod"," 时连接前会要求输入 ",[19,222,223],{"code":223},"yes"," 二次确认，防手滑。",[15,226,227,230],{},[46,228,229],{},"2. 录密码","：",[101,232,235],{"className":233,"code":234,"language":106,"meta":107},[104],"db auth shop-test\n",[19,236,234],{"__ignoreMap":107},[15,238,239,240,243,244,247],{},"交互输入，存进 ",[19,241,242],{"code":242},"~/.mylogin.cnf","。这一步是 ",[19,245,246],{"code":246},"mysql_config_editor"," 干的，密码不会进注册表，所以注册表可以放心提交到 dotfiles。",[15,249,250,230],{},[46,251,252],{},"3. 生效",[101,254,257],{"className":255,"code":256,"language":106,"meta":107},[104],"exec zsh\n",[19,258,256],{"__ignoreMap":107},[15,260,261,262,264],{},"之后 ",[19,263,32],{"code":32}," 直接可用，额外参数会透传：",[101,266,269],{"className":267,"code":268,"language":106,"meta":107},[104],"shop-test -e \"show tables\"\n",[19,270,268],{"__ignoreMap":107},[39,272,273],{"id":273},"加一个服务器或其他命令",[15,275,276,277,280],{},"两步。",[19,278,279],{"code":279},"sc edit"," 加一行，第一个字段是短名，余下整行都是要执行的命令：",[101,282,285],{"className":283,"code":284,"language":199,"meta":107},[197],"# 服务器（主机细节写在 ~/.ssh/conf.d/ 里）\naliyun-01        ssh aliyun-01\naliyun-02        ssh aliyun-02\n\n# 端口转发：本地 13306 通到测试库\ntun-shop         ssh -N -L 13306:db-test.internal.example:3306 bastion\n\n# k8s\nk8s-test         kubectl --context=test\n",[19,286,284],{"__ignoreMap":107},[15,288,289,290,293],{},"然后 ",[19,291,292],{"code":292},"sc reload","。只支持整行注释，不支持行尾注释。",[15,295,296,297,300,301,304,305,189,308,311,312,212],{},"短名撞上已有命令时会被跳过并告警，不会覆盖系统命令。试过写一个叫 ",[19,298,299],{"code":299},"ls"," 的短名，结果是它被跳过，",[19,302,303],{"code":303},"whence -w ls"," 仍然是 ",[19,306,307],{"code":307},"command",[19,309,310],{"code":310},"sc ls"," 里那行标成「冲突/未生效」。数据库那边同理，裸短名撞了就退回只能用 ",[19,313,314],{"code":314},"mysql-\u003Cname>",[39,316,318],{"id":317},"ssh-主机定义","SSH 主机定义",[15,320,321,324,325,328,329,230],{},[19,322,323],{"code":323},"~/.ssh/config"," 只留 ",[19,326,327],{"code":327},"Include"," 和全局默认，主机按用途拆到 ",[19,330,331],{"code":331},"conf.d/",[101,333,338],{"className":334,"code":336,"language":337,"meta":107},[335],"language-sshconfig","Include conf.d/*.conf\n\nHost *\n    AddKeysToAgent yes\n    UseKeychain yes\n    ControlMaster auto\n    ControlPath ~/.ssh/cm/%C\n    ControlPersist 5m\n    ServerAliveInterval 60\n    IdentitiesOnly yes\n","sshconfig",[19,339,336],{"__ignoreMap":107},[15,341,342,230],{},[19,343,344],{"code":344},"conf.d/10-servers.conf",[101,346,349],{"className":347,"code":348,"language":337,"meta":107},[335],"Host aliyun-01\n    HostName 1.2.3.4\n    User work\n    IdentityFile ~/.ssh/id_ed25519\n\nHost shop-test-*\n    User work\n    ProxyJump bastion\n",[19,350,348],{"__ignoreMap":107},[10,352,355],{"title":353,"type":354},"Include 必须放在最前面","warning",[15,356,357,358,360,361,364],{},"ssh 是「首次取到的值生效」。",[19,359,327],{"code":327}," 放到 ",[19,362,363],{"code":363},"Host *"," 后面的话，分片里的设置会被全局默认盖掉。",[15,366,367,370,371,212],{},[19,368,369],{"code":369},"ControlPath"," 那个目录要自己建：",[19,372,373],{"code":373},"mkdir -p ~/.ssh/cm && chmod 700 ~/.ssh/cm",[15,375,376,377,380,381,384],{},"顺带说下这几个全局默认的作用：",[19,378,379],{"code":379},"ControlMaster"," 是连接复用，走跳板机时第二次连接秒开；",[19,382,383],{"code":383},"IdentitiesOnly"," 让 ssh 只试配置里指定的密钥，密钥多了能避免 too many authentication failures。",[15,386,387,388,391,392,395,396,399],{},"zsh 5.9 的 ",[19,389,390],{"code":390},"_ssh_hosts"," 补全函数会展开 ",[19,393,394],{"code":394},"include","，所以拆分之后 ",[19,397,398],{"code":398},"ssh"," + Tab 照样能列出所有 Host。",[39,401,402],{"id":402},"换机器怎么迁",[15,404,405,406,409,410,212],{},"能直接拷的：",[19,407,408],{"code":408},"~/.config/zsh/"," 整个目录、",[19,411,412],{"code":412},"~/.ssh/conf.d/*.conf",[15,414,415,416,418,419,422,423,426,427,430],{},"不能拷的：",[19,417,242],{"code":242},"（每台机器重新 ",[19,420,421],{"code":421},"db auth","）、",[19,424,425],{"code":425},"~/.ssh/id_*"," 私钥、含内网 IP 的分片（用 ",[19,428,429],{"code":429},"90-"," 前缀 + gitignore 隔离）。",[15,432,433],{},"做成 dotfiles：",[101,435,438],{"className":436,"code":437,"language":106,"meta":107},[104],"mkdir -p ~/.dotfiles && cd ~/.dotfiles && git init\nmv ~/.config/zsh zsh && ln -s ~/.dotfiles/zsh ~/.config/zsh\nmv ~/.zshrc zshrc && ln -s ~/.dotfiles/zshrc ~/.zshrc\n",[19,439,437],{"__ignoreMap":107},[15,441,442,445],{},[19,443,444],{"code":444},"~/.ssh"," 不要整体入库，里面有私钥。",[39,447,448],{"id":448},"注意事项",[450,451,452,456,461],"ul",{},[453,454,455],"li",{},"生成的是 alias，只在交互式 shell 生效。写 shell 脚本时要用完整命令。",[453,457,458,460],{},[19,459,242],{"code":242}," 是混淆存储不是加密，MySQL 官方文档明确说它只防无意窥视。能读到 home 目录的人就能解出密码。",[453,462,463,464,467,468,470],{},"改完两张表都要 ",[19,465,466],{"code":466},"exec zsh","（或 ",[19,469,292],{"code":292},"）才生效，当前窗口不会自动重载。",[39,472,474],{"id":473},"附录完整代码","附录：完整代码",[476,477,479],"h3",{"id":478},"rcd50-dbzsh","rc.d/50-db.zsh",[101,481,484],{"className":482,"code":483,"language":126,"meta":107},[124],"# ══════════════════════════════════════════════════════════════════════\n# 数据库快捷连接\n#\n#   db ls                    列出所有已登记连接\n#   db show   \u003Cname>         查看某连接明细（不含密码）\n#   db auth   \u003Cname>         录入/更新密码到 ~/.mylogin.cnf（交互输入）\n#   db forget \u003Cname>         删除本机保存的密码\n#   db connect \u003Cname> [...]  连接（额外参数透传给客户端）\n#   db q      \u003Cname> \u003Csql>   执行一条 SQL 并返回结果\n#   db \u003Cname>                = db connect \u003Cname>\n#\n# 每个连接会生成两个别名：\u003Cname> 和 \u003Cengine>-\u003Cname>\n# 连接信息见 $DB_REGISTRY，密码存在 ~/.mylogin.cnf，永不写入本仓库。\n# ══════════════════════════════════════════════════════════════════════\n\nexport DB_REGISTRY=\"${DB_REGISTRY:-$ZSH_CONFIG_DIR/db/connections.conf}\"\n\n# 内部：输出注册表里的有效数据行（去掉注释与空行）\n_db_rows() {\n    [[ -r $DB_REGISTRY ]] || { print -ru2 \"db: 注册表不存在或不可读：$DB_REGISTRY\"; return 1 }\n    awk '!/^[[:space:]]*(#|$)/' \"$DB_REGISTRY\"\n}\n\n# 内部：按短名取一行；找不到返回 1\n_db_row() {\n    local line\n    line=$(_db_rows | awk -v n=\"$1\" '$1 == n { print; exit }') || return 1\n    [[ -n $line ]] || { print -ru2 \"db: 未登记的连接：$1\"; return 1 }\n    print -r -- \"$line\"\n}\n\n# 内部：所有短名，供补全使用\n_db_names() { _db_rows 2>/dev/null | awk '{print $1}' }\n\n# 内部：该连接对应的 login-path 名（加前缀避免与其他工具冲突）\n_db_login_path() { print -r -- \"db-$1\" }\n\n# 内部：本机是否已保存该连接的密码\n_db_has_auth() {\n    [[ -n $(mysql_config_editor print --login-path=\"$(_db_login_path \"$1\")\" 2>/dev/null) ]]\n}\n\n# 内部：短名是否会覆盖已有的命令/函数/内建\n_db_conflict() {\n    (( $+commands[$1] || $+functions[$1] || $+builtins[$1] ))\n}\n\n# 内部：该连接实际可直接敲的命令（裸短名优先，其次 \u003Cengine>-\u003Cname>）\n_db_cmd_of() {\n    if [[ -n ${aliases[$1]} ]]; then\n        print -r -- \"$1\"\n    elif [[ -n ${aliases[${2}-${1}]} ]]; then\n        print -r -- \"${2}-${1}\"\n    else\n        print -r -- \"db connect $1\"\n    fi\n}\n\ndb() {\n    local cmd=$1\n    case $cmd in\n        ls|list|'')\n            { print -r -- \"NAME│COMMAND│HOST│PORT│USER│DATABASE│ENV│AUTH\"\n              local -a f\n              _db_rows | while read -rA f; do\n                  print -r -- \"$f[1]│$(_db_cmd_of $f[1] $f[2])│$f[3]│$f[4]│$f[5]│$f[6]│$f[7]│$(_db_has_auth $f[1] && print '✔' || print '✘')\"\n              done\n            } | column -t -s '│'\n            ;;\n\n        show)\n            local -a f; f=(${=$(_db_row \"$2\")}) || return 1\n            print -r -- \"name      : $f[1]\"\n            print -r -- \"engine    : $f[2]\"\n            print -r -- \"host:port : $f[3]:$f[4]\"\n            print -r -- \"user      : $f[5]\"\n            print -r -- \"database  : $f[6]\"\n            print -r -- \"env       : $f[7]\"\n            print -r -- \"login-path: $(_db_login_path $f[1]) ($(_db_has_auth $f[1] && print '已保存密码' || print '未保存密码'))\"\n            print -r -- \"alias     : $f[2]-$f[1]\"\n            ;;\n\n        auth)\n            local -a f; f=(${=$(_db_row \"$2\")}) || return 1\n            print -r -- \"为 $f[1] ($f[5]@$f[3]:$f[4]) 录入密码，将保存到 ~/.mylogin.cnf\"\n            mysql_config_editor set --login-path=\"$(_db_login_path $f[1])\" --password \\\n                && print -r -- \"已保存。现在可以直接执行：$f[1]\"\n            ;;\n\n        forget)\n            local -a f; f=(${=$(_db_row \"$2\")}) || return 1\n            mysql_config_editor remove --login-path=\"$(_db_login_path $f[1])\" \\\n                && print -r -- \"已删除 $f[1] 的本机凭据。\"\n            ;;\n\n        connect|q|query)\n            local -a f; f=(${=$(_db_row \"$2\")}) || return 1\n            shift 2\n            local name=$f[1] engine=$f[2] host=$f[3] port=$f[4] user=$f[5] database=$f[6] env=$f[7]\n\n            if ! _db_has_auth $name; then\n                print -ru2 \"db: 尚未保存 $name 的密码，请先执行：db auth $name\"\n                return 1\n            fi\n\n            # 生产环境二次确认，防手滑\n            if [[ $env == prod* ]]; then\n                print -n -- \"⚠️  $name 是生产环境，确认连接？(输入 yes) \"\n                local answer; read -r answer\n                [[ $answer == yes ]] || { print -r -- \"已取消。\"; return 1 }\n            fi\n\n            local -a args\n            case $engine in\n                mysql)\n                    args=(--login-path=\"$(_db_login_path $name)\"\n                          --host=\"$host\" --port=\"$port\" --user=\"$user\")\n                    [[ $database != - ]] && args+=(--database=\"$database\")\n                    if [[ $cmd == q || $cmd == query ]]; then\n                        command mysql \"${args[@]}\" --table --execute=\"$*\"\n                    else\n                        command mysql \"${args[@]}\" \"$@\"\n                    fi\n                    ;;\n                *)\n                    print -ru2 \"db: 暂不支持 engine=$engine（在这里扩展 case 分支）\"\n                    return 1\n                    ;;\n            esac\n            ;;\n\n        edit)   ${EDITOR:-vi} \"$DB_REGISTRY\" ;;\n        help|-h|--help)\n            print -r -- \"用法: db {ls|show|auth|forget|connect|q|edit} [name] [args...]\"\n            ;;\n        *)\n            # db \u003Cname> 等价于 db connect \u003Cname>\n            db connect \"$@\"\n            ;;\n    esac\n}\n\n# 为每个连接生成两个别名：裸短名 + \u003Cengine>-\u003Cname>\n# 裸短名撞上已有命令时跳过并告警，绝不覆盖系统命令。\nif [[ -r $DB_REGISTRY ]]; then\n    typeset -a _db_f _db_skipped\n    while read -rA _db_f; do\n        if _db_conflict \"${_db_f[1]}\"; then\n            _db_skipped+=(\"${_db_f[1]}\")\n        else\n            alias \"${_db_f[1]}\"=\"db connect ${_db_f[1]}\"\n        fi\n        _db_conflict \"${_db_f[2]}-${_db_f[1]}\" \\\n            || alias \"${_db_f[2]}-${_db_f[1]}\"=\"db connect ${_db_f[1]}\"\n    done \u003C \u003C(_db_rows 2>/dev/null)\n\n    if (( $#_db_skipped )); then\n        print -ru2 \"db: 以下短名与已有命令冲突，只能用 \u003Cengine>-\u003Cname> 形式：${_db_skipped[*]}\"\n    fi\n    unset _db_f _db_skipped\nfi\n\n# 补全：db 的子命令与连接名\n_db_complete() {\n    local -a subcmds\n    subcmds=(ls show auth forget connect q edit help)\n    if (( CURRENT == 2 )); then\n        compadd -X '子命令' -- $subcmds\n        compadd -X '连接' -- $(_db_names)\n    elif (( CURRENT == 3 )); then\n        compadd -- $(_db_names)\n    fi\n}\ncompdef _db_complete db\n",[19,485,483],{"__ignoreMap":107},[476,487,489],{"id":488},"rcd55-shortcutszsh","rc.d/55-shortcuts.zsh",[101,491,494],{"className":492,"code":493,"language":126,"meta":107},[124],"# ══════════════════════════════════════════════════════════════════════\n# 命令快捷方式：把 shortcuts.conf 里的每一行变成一个可直接执行的短名\n#\n#   sc ls        查看全部快捷方式\n#   sc show \u003Cn>  查看某个短名展开成什么\n#   sc edit      编辑快捷表\n#   sc reload    重载 shell 使改动生效\n#\n# 生成的是 alias，因此只在交互式 shell 生效；脚本里请写完整命令。\n# ══════════════════════════════════════════════════════════════════════\n\nexport SHORTCUTS_FILE=\"${SHORTCUTS_FILE:-$ZSH_CONFIG_DIR/shortcuts.conf}\"\n\n# 内部：输出有效数据行（去掉注释与空行）\n_sc_rows() {\n    [[ -r $SHORTCUTS_FILE ]] || { print -ru2 \"sc: 快捷表不存在或不可读：$SHORTCUTS_FILE\"; return 1 }\n    awk '!/^[[:space:]]*(#|$)/' \"$SHORTCUTS_FILE\"\n}\n\n# 内部：短名是否会覆盖已有的命令/函数/内建，或已被前序分片占用的 alias\n# （定义完全相同时不算冲突，便于重复 source）\n_sc_conflict() {\n    (( $+commands[$1] || $+functions[$1] || $+builtins[$1] )) && return 0\n    [[ -n ${aliases[$1]} && ${aliases[$1]} != $2 ]]\n}\n\n# 加载：逐行生成 alias，撞名则跳过并告警\nif [[ -r $SHORTCUTS_FILE ]]; then\n    typeset -a _sc_skipped\n    while read -r _sc_name _sc_cmd; do\n        [[ -n $_sc_name && -n $_sc_cmd ]] || continue\n        if _sc_conflict $_sc_name \"$_sc_cmd\"; then\n            _sc_skipped+=(\"$_sc_name\")\n            continue\n        fi\n        alias \"$_sc_name\"=\"$_sc_cmd\"\n    done \u003C \u003C(_sc_rows 2>/dev/null)\n\n    if (( $#_sc_skipped )); then\n        print -ru2 \"sc: 以下短名与已有命令冲突，已跳过：${_sc_skipped[*]}\"\n        print -ru2 \"    请在 $SHORTCUTS_FILE 中改名\"\n    fi\n    unset _sc_name _sc_cmd _sc_skipped\nfi\n\nsc() {\n    case ${1:-ls} in\n        ls|list)\n            { print -r -- \"SHORTCUT│COMMAND│STATUS\"\n              local n c\n              _sc_rows | while read -r n c; do\n                  [[ -n $n && -n $c ]] || continue\n                  print -r -- \"$n │$c│$(if [[ ${aliases[$n]} == $c ]]; then print '生效'; else print '冲突/未生效'; fi)\"\n              done\n            } | column -t -s '│'\n            ;;\n\n        show)\n            local n=$2\n            [[ -n $n ]] || { print -ru2 \"用法: sc show \u003C短名>\"; return 1 }\n            local c\n            c=$(_sc_rows | awk -v n=\"$n\" '$1 == n { $1=\"\"; sub(/^[ \\t]+/,\"\"); print; exit }')\n            [[ -n $c ]] || { print -ru2 \"sc: 快捷表中没有 $n\"; return 1 }\n            print -r -- \"$n → $c\"\n            [[ ${aliases[$n]} == $c ]] || print -ru2 \"（当前未生效：可能与已有命令冲突，或尚未 sc reload）\"\n            ;;\n\n        edit)   ${EDITOR:-vi} \"$SHORTCUTS_FILE\" ;;\n        reload) exec zsh ;;\n        help|-h|--help)\n            print -r -- \"用法: sc {ls|show \u003C短名>|edit|reload}\"\n            ;;\n        *)\n            print -ru2 \"sc: 未知子命令 $1（可用：ls show edit reload help）\"\n            return 1\n            ;;\n    esac\n}\n\n# 补全：sc 的子命令与已登记短名\n_sc_complete() {\n    if (( CURRENT == 2 )); then\n        compadd -X '子命令' -- ls show edit reload help\n    elif (( CURRENT == 3 )) && [[ $words[2] == show ]]; then\n        compadd -- $(_sc_rows 2>/dev/null | awk '{print $1}')\n    fi\n}\ncompdef _sc_complete sc\n",[19,495,493],{"__ignoreMap":107},{"title":107,"searchDepth":497,"depth":497,"links":498},4,[499,501,502,503,504,505,506,507,508],{"id":41,"depth":500,"text":41},2,{"id":99,"depth":500,"text":99},{"id":131,"depth":500,"text":131},{"id":180,"depth":500,"text":180},{"id":273,"depth":500,"text":273},{"id":317,"depth":500,"text":318},{"id":402,"depth":500,"text":402},{"id":448,"depth":500,"text":448},{"id":473,"depth":500,"text":474,"children":509},[510,512],{"id":478,"depth":511,"text":479},3,{"id":488,"depth":511,"text":489},[514],"技术",true,"2026-07-26 18:05:00","用两张配置表管住数据库和服务器的连接命令，短名直接可敲，密码不落明文。",false,"md",null,{"slots":522},{},"/2026/terminal-shortcuts",{"text":525,"minutes":526,"time":527,"words":528},"14 min read",13.065,783900,2613,{"title":5,"description":517},{"loc":523},"posts/2026/terminal-shortcuts",[126,533,534,535,536],"终端","MySQL","SSH","dotfiles","tech","r8yCld-5DOmJoqOoV-QFNmvwAyShWre4ijdxTIVyEwY",[540,520],{"title":541,"path":542,"stem":543,"date":544,"type":537,"children":-1},"Java 的 ACM 常用模板","/2026/acm-java-template","posts/2026/acm-java-template","2026-04-04 15:36:18",1786267638946]