{"id":13442157,"url":"https://github.com/emacs-china/Spacemacs-rocks","last_synced_at":"2025-03-20T13:32:43.511Z","repository":{"id":37390661,"uuid":"44011650","full_name":"emacs-china/Spacemacs-rocks","owner":"emacs-china","description":"Happy Hacking Emacs \u0026 Spacemacs (Simplified Chinese)","archived":false,"fork":false,"pushed_at":"2024-03-04T04:40:34.000Z","size":1067,"stargazers_count":2122,"open_issues_count":52,"forks_count":322,"subscribers_count":137,"default_branch":"master","last_synced_at":"2025-03-16T22:09:06.634Z","etag":null,"topics":["emacs","learn-emacs","spacemacs"],"latest_commit_sha":null,"homepage":"http://book.emacs-china.org","language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emacs-china.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":"CONTRIBUTING.org","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-10-10T13:27:28.000Z","updated_at":"2025-03-12T08:00:43.000Z","dependencies_parsed_at":"2023-01-19T18:16:41.165Z","dependency_job_id":"43112b3f-39ef-499d-9e0d-83d0373f1a63","html_url":"https://github.com/emacs-china/Spacemacs-rocks","commit_stats":{"total_commits":265,"total_committers":22,"mean_commits":"12.045454545454545","dds":0.6867924528301887,"last_synced_commit":"3539adc4dd040fe2673dcd207511de39cfc81168"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emacs-china%2FSpacemacs-rocks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emacs-china%2FSpacemacs-rocks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emacs-china%2FSpacemacs-rocks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emacs-china%2FSpacemacs-rocks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emacs-china","download_url":"https://codeload.github.com/emacs-china/Spacemacs-rocks/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244619232,"owners_count":20482387,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["emacs","learn-emacs","spacemacs"],"created_at":"2024-07-31T03:01:42.336Z","updated_at":"2025-03-20T13:32:43.497Z","avatar_url":"https://github.com/emacs-china.png","language":"CSS","funding_links":[],"categories":["CSS"],"sub_categories":[],"readme":"# -*- mode: org; -*-\n\n#+HTML_HEAD: \u003clink rel=\"stylesheet\" type=\"text/css\" href=\"readtheorg/css/readtheorg.css\"/\u003e\n#+HTML_HEAD: \u003clink rel=\"stylesheet\" type=\"text/css\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.3.0/styles/default.min.css\"/\u003e\n\n#+HTML_HEAD: \u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js\"\u003e\u003c/script\u003e\n#+HTML_HEAD: \u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/js/bootstrap.min.js\"\u003e\u003c/script\u003e\n# #+HTML_HEAD: \u003cscript type=\"text/javascript\" src=\"readtheorg/js/jquery.stickytableheaders.js\"\u003e\u003c/script\u003e // www.pirilamp.org/styles/lib/js/jquery.stickytableheaders.js 404 Now\n#+HTML_HEAD: \u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/sticky-table-headers/0.1.19/js/jquery.stickytableheaders.min.js\"\u003e\u003c/script\u003e\n#+HTML_HEAD: \u003cscript type=\"text/javascript\" src=\"readtheorg/js/readtheorg.js\"\u003e\u003c/script\u003e\n#+HTML_HEAD: \u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.3.0/highlight.min.js\"\u003e\u003c/script\u003e\n#+HTML_HEAD: \u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.3.0/languages/lisp.min.js\"\u003e\u003c/script\u003e\n#+HTML_HEAD: \u003cscript\u003ehljs.initHighlightingOnLoad();\u003c/script\u003e\n\n#+AUTHOR: zilongshanren\n#+CREATOR: li-xinyang\n#+TITLE: Master Emacs in 21 Days\n#+EMAIL: guanghui8827@gmail.com\n#+OPTIONS: toc:3 num:nil\n#+STARTUP: showall\n#+OPTIONS: ^:nil\n\n\n* 21 天学会 Emacs（2022 Edition）\n\n*GitHub* [[https://github.com/emacs-china/Spacemacs-rocks][Emacs Rocks]] *作者* [[https://github.com/zilongshanren/][zilongshanren]] *编者* [[https://github.com/li-xinyang][li-xinyang]], [[https://github.com/lsytj0413][lsytj0413]]\n\n在这一季中我们计划用 21 天学习 Emacs 的使用。从基础安装开始到可以\n运用到工作生产环节中。为了确保学习质量，请务必完成和理解计划中的每一项学习任务。(新的系列全部使用 Vallina Emacs)\n\nUpdate（2022 年 1 月 15 日）: 本系列视频教程最早录制于 2016 年，距今已经有 5 年多的历史了，\n在此期间 Emacs 社区又进化了非常多。出现了更活跃的 Doom Emacs 社区配置，拥有 GCC Emacs，所以\n现在回头来看当时的视频教程，显得多少有些过时了。以前 21 天的视频教程显得有些冗长，我打算在 2022 年\n更新所有这些视频教程，并且控制每一个视频的时长（20 分钟左右），希望这个系列教程能够帮助到大家。\n\n*本视频的代码仓库：* https://gitee.com/emacs-china/emacs.d\n\n原来 21 天的视频地址：\n\n- [[https://www.youtube.com/watch?v=0hpVuoyO8_o\u0026list=PLZx9tb9Niew8qMjpCjeYnsezCE-s5mKw_][Youtube]]\n- [[https://www.bilibili.com/video/BV1sp4y1Y73S?from=search\u0026seid=10747273033486124295\u0026spm_id_from=333.337.0.0][Bilibili]]\n  \n原来 21 天的教程地址：\n\n[[http://book1.emacs-china.org/][《21天学会Emacs》]]\n\n* 第一天：准备开始(安装与改键)\n\n视频地址如下：\n\n- [[https://www.youtube.com/watch?v=0HZa7ttGLiU][Youtube]]\n- [[https://www.bilibili.com/video/BV12P4y1j7EL/][Bilibili]]\n\n*说在最前面*\n\n如果你第一次听说 Emacs 你可以在[[http://emacs.sexy/][性感的 Emacs（Emacs is Sexy）]]一文中找到使用它的理\n由！我相信你一定会被它的强大所吸引。\n\n如果你还没有安装 Emacs 可以在 Doom Emacs 的安装文档中查找[[https://github.com/hlissner/doom-emacs/blob/master/docs/getting_started.org#install][安装方法]]，根据你所使用的操作系统去下载对应\n版本的 Emacs 就行了。（新手不推荐从源码进行编译安装，因为这会比较困难）\n\n因为考虑到比较多的用户之前可能没有接触过 Mac 或者 Linux，所以新的系列视频我会直接使用 Windows 系统来\n进行演示。Windows 下配置 Emacs 环境可以参考我之前在论坛写的[[https://emacs-china.org/t/windows-emacs/7907][文章]]。\n\n由于 Windows 系统的一些限制，某一些 Emacs 的功能（Magit，lsp 等）表现并不是很好（主要指的是性能），读者可以\n尝试安装 WLS 来使用 Emacs，具体方法可以参考[[https://hkvim.com/post/windows-setup/][这篇文章]]。\n\n在开始本教程之前请务必先完成 Emacs 提供的官方教程（完成时间大约 30 分钟），它可\n以通过使用 =C-h t= （同时按住 Ctrl 与 h 键，接着按 t 键 =t= 在这里代表 tutorial）\n在 Emacs 中直接将其打开。（当然你也可以在观看视频之后再去阅读 Emacs Tutorial）\n\nEmacs Lisp 是 Emacs 所用的编程语言，你可以在阅读[[https://learnxinyminutes.com/docs/elisp/][这篇教程（Learn X in Y Minutes）]]\n后很快地了解它的基础用法。\n\n** 基础操作\n在讲解基本操作之前，先跟大家讲一下改键。改键的作用除了可以让你的小拇指更健康以外，还可以统一我们的交流语言，\n让大家后面学习过程可以更轻松。（这部分如果没有相关基础，强烈建议先看视频是怎么操作的）\n\nWindows 键盘布局：\n\n[[./Images/1600px-KB_United_States-NoAltGr.svg.png]]\n\nWindows 改键方法：\n\n使用 SharpKeys 来把 Left Window 键改成 Left Alt 键，Left Alt 键改成 App 键，大小写键改成 Ctrl 键。\n\n[[./Images/sharpKeys.png]]\n\nEmacs 默认 Alt 键就是 Meta，而 App 键我们改成 super 键，可以通过下面的 Elisp 代码来完成。\n#+begin_src emacs-lisp\n  (setq w32-apps-modifier 'super)       ; 通过SharpKeys改成了 Application\n#+end_src\n\nMac 键盘布局：\n\n[[./Images/mac-keyboard-layout.jpeg]]\n\nMac 下面大小写键改成 Ctrl 键（参考视频），Mac 系列只需要修改这个按键，其他的按键可以通过 Elisp 来修改：\n\n#+begin_src emacs-lisp\n  (setq mac-option-modifier 'meta\n        mac-command-modifier 'super)\n#+end_src\n\n常见符号所代表的意义如下\n\n- M(eta)：统一改到 option 键（Mac），left windows 键（Windows）\n- s(uper)：统一改到 command 键（Mac），left Alt 键（windows）\n- S(Shift)：不用修改\n- C(trl)：统一改成 Caps Lock（大小写切换键，这样可以拯救你的小拇指健康）\n\n\n光标的移动是编辑器中最常用的操作所以必须熟知。（只需要掌握这些基础的光标移动操作，后续我会介绍 Vim 的光标移动操作，\n我个人认为 Vim 的光标移动更高效，大家先熟知这几个常用的移动命令即可。）\n\n-  =C-f= 为前移一个字符， =f= 代表 forward。\n-  =C-b= 为后移一个字符， =b= 代表 backward。\n-  =C-p= 为上移至前一行， =p= 代表 previous。\n-  =C-n= 为上移至下一行， =n= 代表 next。\n-  =C-a= 为移至行首， =a= 代表 ahead。\n-  =C-e= 为移至行尾， =e= 代表 end。\n\n为什么不使用鼠标而去学习这些奇怪的按键组合呢？因为这些按键在某些时候是非常高效的，比如在 Emacs 里面，Shell 终端里面，\n甚至整个 Mac 系统都内置了这种按键。我本人在使用 Vim 或者其他 IDE 的时候也会使用 Emacs 的这套按键。\n\n*学习可以迁移的技能*，这一点非常重要！一旦学会了将可以终身受用。\n\n现在我们可以把 Mac 下面的复制、粘贴、剪切、全选等命令移植到 Emacs 中来了，并且这一套按键是跨平台的。\n\n#+begin_src emacs-lisp\n  (global-set-key (kbd \"s-a\") 'mark-whole-buffer) ;;对应Windows上面的Ctrl-a 全选\n  (global-set-key (kbd \"s-c\") 'kill-ring-save) ;;对应Windows上面的Ctrl-c 复制\n  (global-set-key (kbd \"s-s\") 'save-buffer) ;; 对应Windows上面的Ctrl-s 保存\n  (global-set-key (kbd \"s-v\") 'yank) ;对应Windows上面的Ctrl-v 粘贴\n  (global-set-key (kbd \"s-z\") 'undo) ;对应Windows上面的Ctrol-z 撤销\n  (global-set-key (kbd \"s-x\") 'kill-region) ;对应Windows上面的Ctrol-x 剪切\n#+end_src\n\n* 第二天： 打造属于你的记事本\n视频地址如下：\n\n- [[https://www.youtube.com/watch?v=fxE1L-scvbk][Youtube]]\n- [[https://www.bilibili.com/video/BV1jY411h7Ts/][Bilibili]]\n\n** 内置功能\n\nEmacs 功能强大，但是部分功能默认情况下并未开启。下面就有几个例子，\n\n编辑器内显示行号可使用 =M-x linum-mode= 来开启。\n\n*获取帮助*\n\nEmacs 是一个富文档编辑器（Self document, extensible editor）而下面的三种方法在学\n习 Emacs 的过程中也非常重要。他们分别是，\n\n-  =C-h k= 寻找快捷键的帮助信息\n-  =C-h v= 寻找变量的帮助信息\n-  =C-h f= 寻找函数的帮助信息\n\n*** 给 Windows 右键菜单添加 OpenWithEmacs 功能\n#+begin_src\nWindows Registry Editor Version 5.00\n\n[HKEY_CLASSES_ROOT\\*\\shell]\n[HKEY_CLASSES_ROOT\\*\\shell\\openwemacs]\n@=\"\u0026Edit with Emacs\"\n[HKEY_CLASSES_ROOT\\*\\shell\\openwemacs\\command]\n@=\"C:\\\\emax64\\\\bin\\\\emacsclientw.exe -n \\\"%1\\\"\"\n[HKEY_CLASSES_ROOT\\Directory\\shell\\openwemacs]\n@=\"Edit \u0026with Emacs\"\n[HKEY_CLASSES_ROOT\\Directory\\shell\\openwemacs\\command]\n@=\"C:\\\\emax64\\\\bin\\\\emacsclientw.exe -n \\\"%1\\\"\"\n#+end_src\n\n使用这个 OpenWithEmacs 的功能，Emacs 需要开启 Server Mode，代码如下：\n#+begin_src emacs-lisp\n  (server-mode 1)\n#+end_src\n* 第三天：Elisp 基础、Org 基础和包管理器\n\n视频地址如下：\n- [[https://www.bilibili.com/video/BV1yP4y177xj?spm_id_from=333.999.0.0][Bilibili]]\n- [[https://www.youtube.com/watch?v=-tX66neahhM\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=4\u0026t=3s][Youtube]]\n\n\n** 学习基础 Elisp\n\n请务必完成[[https://learnxinyminutes.com/docs/elisp/][这篇教程（Learn X in Y Minutes）]]来了解 Elisp 的使用（阅读时间大约 15\n分钟），你也可以在[[https://learnxinyminutes.com/docs/zh-cn/elisp-cn/][这里]]找到它的中文版。Emacs Lisp 为一个函数式的语言，所以它全部\n功能都是由函数来实现的。\n\n下面为一些简单的例子\n\n#+BEGIN_SRC emacs-lisp\n  ;; 2 + 2\n  (+ 2 2)\n\n  ;; 2 + 3 * 4\n  (+ 2 (* 3 4))\n\n  ;; 定义变量\n  (setq name \"username\")\n  (message name) ; -\u003e \"username\"\n\n  ;; 定义函数\n  (defun func ()\n    (message \"Hello, %s\" name))\n\n  ;; 执行函数\n  (func) ; -\u003e Hello, username\n\n  ;; 设置快捷键\n  (global-set-key (kbd \"\u003cf1\u003e\") 'func)\n\n  ;; 使函数可直接被调用可添加 (interactive)\n  (defun func ()\n    (interactive)\n    (message \"Hello, %s\" name))\n#+END_SRC\n\n** 开始 Hacking！\n\nEmacs 的配置文件默认保存在 =~/.emacs.d/init.el= 文件中。（如果其不存在可自行创建，\n配置文件也可保存在 =~/.emacs= 文件中，他们之间的区别我们会在后面做讨论）\n\n**注意：** 如果希望把配置放在 =~/.emacs.d/init.el= 文件中，那么需要手工删除\n=~/.emacs= 文件。\n\n在开始配置之前让我们先来区别 Emacs 中 Major Mode 与 Minor Mode 的区别。Major\nMode 通常是定义对于一种文件类型编辑的核心规则，例如语法高亮、缩进、快捷键绑定等。\n而 Minor Mode 是除去 Major Mode 所提供的核心功能以外的额外编辑功能（辅助功能）。\n例如在下面的配置文件中 =tool-bar-mode= 与 =linum-mode= 等均为 Minor Mode*。\n\n简单来说就是，一种文件类型同时只能存在一种 Major Mode 但是它可以同时激活一种或多\n种 Minor Mode。如果你希望知道当前的模式信息，可以使用 =C-h m= 来显示当前所有开启\n的全部 Minor Mode 的信息。\n\n*简单的编辑器自定义*\n\n下面是一些简单的编辑器配置信息，你需要做的就是将其写入你的配置文件中\n（ =~/.emacs.d/init.el= ）即可。\n\n#+BEGIN_SRC emacs-lisp\n  ;; 关闭工具栏，tool-bar-mode 即为一个 Minor Mode\n  (tool-bar-mode -1)\n\n  ;; 关闭文件滑动控件\n  (scroll-bar-mode -1)\n\n  ;; 显示行号\n  (global-linum-mode 1)\n\n  ;; 更改光标的样式（不能生效，解决方案见第二集）\n  (setq cursor-type 'bar)\n\n  (icomplete-mode 1)\n\n\n  ;; 快速打开配置文件\n  (defun open-init-file()\n    (interactive)\n    (find-file \"~/.emacs.d/init.el\"))\n\n  ;; 这一行代码，将函数 open-init-file 绑定到 \u003cf2\u003e 键上\n  (global-set-key (kbd \"\u003cf2\u003e\") 'open-init-file)\n\n#+END_SRC\n\n在每次编辑配置文件后，刚刚做的修改并不会立刻生效。这时你需要重启编辑器或者重新加\n载配置文件。重新加载配置文件你需要在当前配置文件中使用 =M-x load-file= 双击两次\n回车确认默认文件名，或者使用 =M-x eval-buffer= 去执行当前缓冲区的所有 Lisp 命令。\n你也可以使用 =C-x C-e= 来执行某一行的 Lisp 代码。这些可使刚刚修改的配置文件生效。\n当然你也可以将这些函数绑定为快捷键。\n\n** 插件管理\n\n使用默认的插件管理系统（可在菜单栏 =Options \u003e Manage Emacs Packages= 中找到）安\n装 [[http://company-mode.github.io/][Company]] 插件，他是一个用于代码补全的插件。它的名字代表补全一切的意思（ *Comp*\nlete *Any* thing）。因为默认的插件管理系统提供的插件十分有限，所以我们会在之后的\n几天中继续将其强化。\n\n使用的下面的配置将 Company-mode 在全局模式下激活\n\n#+BEGIN_SRC emacs-lisp\n                                          ; 开启全局 Company 补全\n  (global-company-mode 1)\n\n  ;; company mode 默认选择上一条和下一条候选项命令 M-n M-p\n  (define-key company-active-map (kbd \"C-n\") 'company-select-next)\n  (define-key company-active-map (kbd \"C-p\") 'company-select-previous)\n#+END_SRC\n\n** Org-mode\n\n简单的 Org-mode 使用，它可以列出提纲，并方便地使用 =tab= 键来对其进行展开与关闭。\n=C-c C-t= 可以将一个条目转换成一条待办事件。\n\n#+BEGIN_SRC org\n  ,* 为一级标题\n  ,** 为二级标题\n  ,*** 为三级标题并以此类推\n#+END_SRC\n\n* 第四天：增强 Emacs 补全，让 Hacking 更加有趣和可视化\n\n视频地址如下：\n- [[https://www.youtube.com/watch?v=HzlLxWTD6QY][Youtube]]\n\n- [[https://www.bilibili.com/video/BV1uL4y1t7Lm/][Bilibili]]\n\n** 关于 lexical binding\n#+begin_src emacs-lisp\n  ;;在文件最开头添加地个 文件作用域的变量设置，设置变量的绑定方式\n  ;; -*- lexical-binding: t -*-\n  (let ((x 1))    ; x is lexically bound.\n    (+ x 3))\n  ⇒ 4\n\n  (defun getx ()\n    x)            ; x is used free in this function.\n\n  (let ((x 1))    ; x is lexically bound.\n    (getx))\n  ;;error→ Symbol's value as variable is void: x\n#+end_src\n\n关于[[https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html][lexical binding]] 更多的细节，可以自行阅读 Emacs 的官方文档。\n\n#+begin_src emacs-lisp\n  ;; 更改显示字体大小 16pt\n  ;; http://stackoverflow.com/questions/294664/how-to-set-the-font-size-in-emacs\n  (set-face-attribute 'default nil :height 160);;\n\n  ;;让鼠标滚动更好用\n  (setq mouse-wheel-scroll-amount '(1 ((shift) . 1) ((control) . nil)))\n  (setq mouse-wheel-progressive-speed nil)\n\n#+end_src\n\n** 配置 gnu 和 melpa 镜像\n\n在进行美化之前我们需要配置插件的源（默认的源非常有限），最常使用的是 [[https://melpa.org/][MELPA]]\n（Milkypostman's Emacs Lisp Package Archive）。它有非常多的插件（3000 多个插件）。\n添加源后，我们就可以使用 =M-x package-list-packages=\n来查看所有 MELPA 上的插件了。在表单中可以使用 =i= 来标记安装 =d= 来标记删除，\n=U= 来更新，并用 =x= 来确认。你也可以使用 =u= 来撤销标记操作。\n\n你可以直接将下面的代码复制到你的配置文件顶端，从而直接使用 Melpa 作为插件的源。\n\n\n#+BEGIN_SRC emacs-lisp\n  (require 'package)\n  (setq package-archives '((\"gnu\"   . \"http://elpa.zilongshanren.com/gnu/\")\n\n                           (\"melpa\" . \"http://elpa.zilongshanren.com/melpa/\")))\n  (package-initialize)\n\n  ;;防止反复调用 package-refresh-contents 会影响加载速度\n  (when (not package-archive-contents)\n    (package-refresh-contents))\n\n  ;;modeline上显示我的所有的按键和执行的命令\n  (package-install 'keycast)\n  (keycast-mode t)\n#+END_SRC\n\n** 增强 minibuffer 补全：[[https://github.com/minad/vertico][vertico]] 和 [[https://github.com/oantolin/orderless][Orderless]]\n\n#+begin_src emacs-lisp\n  (package-install 'vertico)\n  (vertico-mode t)\n\n  (package-install 'orderless)\n  (setq completion-styles '(orderless))\n#+end_src\n\n** 配置 [[https://github.com/minad/marginalia][Marginalia]] 增强 minubuffer 的 annotation\n\n#+begin_src emacs-lisp\n  (package-install 'marginalia)\n  (marginalia-mode t)\n\n#+end_src\n\n** minibuffer action 和自适应的 context menu：[[https://github.com/oantolin/embark][Embark]]\n#+begin_src emacs-lisp\n\n  (package-install 'embark)\n  (global-set-key (kbd \"C-;\") 'embark-act)\n  (setq prefix-help-command 'embark-prefix-help-command)\n\n#+end_src\n\n** 增强文件内搜索和跳转函数定义：[[https://github.com/minad/consult][Consult]]\n#+begin_src emacs-lisp\n  (package-install 'consult)\n  ;;replace swiper\n  (global-set-key (kbd \"C-s\") 'consult-line)\n  ;;consult-imenu\n#+end_src\n\n\n* 第五天：手动安装插件和使用外部程序\n\n视频地址如下：\n\n- [[https://www.youtube.com/watch?v=EPZe8Ix_dnU][Youtube]]\n- [[https://www.bilibili.com/video/BV1Kr4y1Y73S/][Bilibili]]\n\n** 手工安装插件和更多 Emacs 内置功能定制\n\n如果你想深入学习 Emacs Lisp 可以阅读 GNU 提供的 [[https://www.gnu.org/software/emacs/manual/html_mono/eintr.html][An Introduction to Programming\nin Emacs Lisp]] 。（也可以 =M-x info= 然后选择 Emacs Lisp Intro）\n\n我们先解决前一天中遇到的一些问题。首先是在对象是一个缓冲区局部变量（Buffer-local\nvariable）的时候，比如这里的 =cursor-type= ，我们需要区分 =setq= 与\n=setq-default= ： =setq= 设置当前缓冲区（Buffer）中的变量值， =setq-default= 设\n置的为全局的变量的值（具体内容可以在 [[http://stackoverflow.com/questions/18172728/the-difference-between-setq-and-setq-default-in-emacs-lisp][StackOverflow 找到]]）。下面是一个例子，用于\n设置光标样式的方法。\n\n\n#+BEGIN_SRC emacs-lisp\n  (setq-default cursor-type 'bar)\n  (show-paren-mode t)\n\n  ;;另外一件安装插件的方法\n  (add-to-list 'load-path (expand-file-name \"~/.emacs.d/awesome-tab/\"))\n\n  (require 'awesome-tab)\n\n  (awesome-tab-mode t)\n\n  (defun awesome-tab-buffer-groups ()\n    \"`awesome-tab-buffer-groups' control buffers' group rules.\n  Group awesome-tab with mode if buffer is derived from `eshell-mode' `emacs-lisp-mode' `dired-mode' `org-mode' `magit-mode'.\n  All buffer name start with * will group to \\\"Emacs\\\".\n  Other buffer group by `awesome-tab-get-group-name' with project name.\"\n    (list\n     (cond\n      ((or (string-equal \"*\" (substring (buffer-name) 0 1))\n           (memq major-mode '(magit-process-mode\n                              magit-status-mode\n                              magit-diff-mode\n                              magit-log-mode\n                              magit-file-mode\n                              magit-blob-mode\n                              magit-blame-mode)))\n       \"Emacs\")\n      ((derived-mode-p 'eshell-mode)\n       \"EShell\")\n      ((derived-mode-p 'dired-mode)\n       \"Dired\")\n      ((memq major-mode '(org-mode org-agenda-mode diary-mode))\n       \"OrgMode\")\n      ((derived-mode-p 'eaf-mode)\n       \"EAF\")\n      (t\n       (awesome-tab-get-group-name (current-buffer))))))\n#+END_SRC\n\n其次就是它使用到了 =quote=, 它其实就是我们之前常常见到的 ='= （单引号）的完全体。\n因为它在 Lisp 中十分常用，所以就提供了简写的方法。\n\n#+BEGIN_SRC emacs-lisp\n  ;; 下面两行的效果完全相同的\n  (quote foo)\n  'foo\n#+END_SRC\n\n=quote= 的意思是不要执行后面的内容，返回它原本的内容（具体请参考下面的例子）\n\n#+BEGIN_SRC emacs-lisp\n  (print '(+ 1 1)) ;; -\u003e (+ 1 1)\n  (print (+ 1 1))  ;; -\u003e 2\n#+END_SRC\n\n更多关于 =quote= 的内容可以在[[https://www.gnu.org/software/emacs/manual/html_node/elisp/Quoting.html][这里]]找到，或者在[[http://stackoverflow.com/questions/134887/when-to-use-quote-in-lisp][这里]]找到 StackOverflow 上对于它的讨论。\n\n因为通常我们的配置文件以及项目文件均使用版本控制系统，所以自动生成的备份文件就显\n得有些多余。我们还可以禁止 Emacs 自动生成备份文件，例如 =init.el~= 。（ =~= 为后\n缀的文件为自动生成的备份文件）我们可以使用下面的方法将其关闭。\n\n#+BEGIN_SRC emacs-lisp\n  (setq make-backup-files nil)\n#+END_SRC\n\n使用下面的配置来加入最近打开过文件的选项让我们更快捷的在图形界面的菜单中打开最近\n编辑过的文件。\n\n#+BEGIN_SRC emacs-lisp\n  (require 'recentf)\n  (recentf-mode 1)\n  (setq recentf-max-menu-item 10)\n\n  ;; 这个快捷键绑定可以用之后的插件 counsel 代替\n  ;; (global-set-key (kbd \"C-x C-r\") 'recentf-open-files)\n#+END_SRC\n\n=require= 的意思为从文件中加载特性，你可以在杀哥的网站读到关于 Emacs Lisp 库系统\n的更多内容，文章在[[http://ergoemacs.org/emacs/elisp_library_system.html][这里]]。\n\n使用下面的配置文件将删除功能配置成与其他图形界面的编辑器相同，即当你选中一段文字\n之后输入一个字符会替换掉你选中部分的文字。\n\n#+BEGIN_SRC emacs-lisp\n  (delete-selection-mode 1)\n#+END_SRC\n\n下面的这些函数可以让你找到不同函数，变量以及快捷键所定义的文件位置。因为非常常用\n所以我们建议将其设置为与查找文档类似的快捷键（如下所示），\n\n-  =find-function= （ =C-h C-f= ）\n-  =find-variable= （ =C-h C-v= ）\n-  =find-function-on-key= （ =C-h C-k= ）\n\n** 使用外网命令行工具\n下载安装 [[https://github.com/m-parashar/emax64/releases/download/20200930/emax.7z][emax]]，配置 emacs 加载路径\n\n#+begin_src emacs-lisp\n  (progn\n    (defvar emax-root (concat (expand-file-name \"~\") \"/emax\"))\n    (defvar emax-bin (concat emax-root \"/bin\"))\n    (defvar emax-bin64 (concat emax-root \"/bin64\"))\n\n    (setq exec-path (cons emax-bin exec-path))\n    (setenv \"PATH\" (concat emax-bin \";\" (getenv \"PATH\")))\n\n    (setq exec-path (cons emax-bin64 exec-path))\n    (setenv \"PATH\" (concat emax-bin64 \";\" (getenv \"PATH\")))\n\n    (setq emacsd-bin (concat user-emacs-directory \"bin\"))\n    (setq exec-path (cons  emacsd-bin exec-path))\n    (setenv \"PATH\" (concat emacsd-bin  \";\" (getenv \"PATH\")))\n\n    ;;可选安装msys64\n    ;;下载地址: http://repo.msys2.org/mingw/sources/\n    (setenv \"PATH\" (concat \"C:\\\\msys64\\\\usr\\\\bin;C:\\\\msys64\\\\mingw64\\\\bin;\" (getenv \"PATH\")))\n\n    ;; (dolist (dir '(\"~/emax/\" \"~/emax/bin/\" \"~/emax/bin64/\" \"~/emax/lisp/\" \"~/emax/elpa/\"))\n    ;;   (add-to-list 'load-path dir))\n    )\n#+end_src\n使用 M-x shell 来学习命令行操作，可以参考 https://missing.csail.mit.edu/2020/ 来学习，living in Emacs。\n* 第六天：Emacs 作为超级前端\n视频地址：\n- [[https://www.youtube.com/watch?v=sr1mFqjE0YM][Youtube]]\n- [[https://www.bilibili.com/video/BV1tm4y1o7pd/][Bilibili]]\n  \n** 使用 Emacs 来打开文件管理器\n#+begin_src emacs-lisp\n  (shell-command-to-string \"explorer.exe C:\\\\\")\n\n  (shell-command-to-string \"explorer.exe ~/.emacs.d\")\n\n  (shell-command-to-string\n   (encode-coding-string\n    (replace-regexp-in-string \"/\" \"\\\\\\\\\"\n                              (format \"explorer.exe %s\" (expand-file-name \"~/.emacs.d\")))\n    'gbk))\n\n  (defun consult-directory-externally (file)\n    \"Open FILE externally using the default application of the system.\"\n    (interactive \"fOpen externally: \")\n    (if (and (eq system-type 'windows-nt)\n             (fboundp 'w32-shell-execute))\n        (shell-command-to-string (encode-coding-string (replace-regexp-in-string \"/\" \"\\\\\\\\\"\n                                                                                 (format \"explorer.exe %s\" (file-name-directory (expand-file-name file)))) 'gbk))\n      (call-process (pcase system-type\n                      ('darwin \"open\")\n                      ('cygwin \"cygstart\")\n                      (_ \"xdg-open\"))\n                    nil 0 nil\n                    (file-name-directory (expand-file-name file)))))\n\n  (define-key embark-file-map (kbd \"E\") #'consult-directory-externally)\n  ;;打开当前文件的目录\n  (defun my-open-current-directory ()\n    (interactive)\n    (consult-directory-externally default-directory))\n\n\n#+end_src\n** 增强 embark 和 consult，批量搜索替换大杀器\n\n#+BEGIN_SRC emacs-lisp\n  (package-install 'embark-consult)\n  (package-install 'wgrep)\n  (setq wgrep-auto-save-buffer t)\n\n  (eval-after-load\n      'consult\n    '(eval-after-load\n         'embark\n       '(progn\n          (require 'embark-consult)\n          (add-hook\n           'embark-collect-mode-hook\n           #'consult-preview-at-point-mode))))\n\n  (define-key minibuffer-local-map (kbd \"C-c C-e\") 'embark-export-write)\n\n  ;;使用ripgrep来进行搜索\n  ;;consult-ripgrep\n\n  ;;everyting\n  ;;consult-locate\n  ;; 配置搜索中文\n  (progn\n    (setq consult-locate-args (encode-coding-string \"es.exe -i -p -r\" 'gbk))\n    (add-to-list 'process-coding-system-alist '(\"es\" gbk . gbk))\n    )\n  (eval-after-load 'consult\n    (progn\n      (setq\n       consult-narrow-key \"\u003c\"\n       consult-line-numbers-widen t\n       consult-async-min-input 2\n       consult-async-refresh-delay  0.15\n       consult-async-input-throttle 0.2\n       consult-async-input-debounce 0.1)\n      ))\n#+END_SRC\n\n** 使用拼音进行搜索\n#+begin_src emacs-lisp\n  (package-install 'pyim)\n\n  (defun eh-orderless-regexp (orig_func component)\n    (let ((result (funcall orig_func component)))\n      (pyim-cregexp-build result)))\n\n\n  (defun toggle-chinese-search ()\n    (interactive)\n    (if (not (advice-member-p #'eh-orderless-regexp 'orderless-regexp))\n        (advice-add 'orderless-regexp :around #'eh-orderless-regexp)\n      (advice-remove 'orderless-regexp #'eh-orderless-regexp)))\n\n  (defun disable-py-search (\u0026optional args)\n    (if (advice-member-p #'eh-orderless-regexp 'orderless-regexp)\n        (advice-remove 'orderless-regexp #'eh-orderless-regexp)))\n\n  ;; (advice-add 'exit-minibuffer :after #'disable-py-search)\n  (add-hook 'minibuffer-exit-hook 'disable-py-search)\n\n  (global-set-key (kbd \"s-p\") 'toggle-chinese-search)\n#+end_src\n\n** Emacs 也很美\n\n高亮当前行，当文本内容很多时可以很容易找到光标的位置。\n\n#+BEGIN_SRC emacs-lisp\n  (global-hl-line-mode 1)\n#+END_SRC\n\n*安装主题*\n\n#+BEGIN_SRC emacs-lisp\n  (package-install 'monokai-theme)\n#+END_SRC\n\n然后使用下面的配置使其每次打开编辑器时加载主题，\n\n#+BEGIN_SRC emacs-lisp\n  (load-theme 'monokai 1)\n#+END_SRC\n\n\n使用 =M-x customize-group= 后选择对应的插件名称，可以进入可视化选项区对指定的插\n件做自定义设置。当选择 Save for future session 后，刚刚做的设计就会被保存在你的\n配置文件（ =init.el= ）中。关于各个插件的安装与使用方法通常都可以在其官方页面找\n到（GitHub Pages 或者是项目仓库中的 README 文件）。我们强烈建议大家在安装这些插\n件后阅读使用方法来更好的将它们使用到你的日常工作当中使效率最大化。\n\n* 第七天：模块化配置文件管理\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=_imJVq7KNvA][Youtube]]\n- [[https://www.bilibili.com/video/BV1yR4y1P7sD/?vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n** 使用多文件存储配置文件\n\n将不同的配置代码放置到不同的文件中，使其模块化，这让我们的后续维护变得更加简单。\n下面是我们现在的 =~/.emacs.d/= 目录中的样子，\n\n#+BEGIN_EXAMPLE\n├── auto-save-list # 自动生成的保存数据\n├── elpa           # 下载的插件目录\n├── init.el        # 我们的配置文件\n└── recentf        # 最近访问的文件列表\n#+END_EXAMPLE\n\n通常我们只保存配置文件和对其进行版本控制，其他的插件均为在第一次使用编辑器时再通\n过网络重新下载，当然你也可以选择将全部配置文件进行版本控制来保证自己时刻拥有最稳\n定的生产环境。\n\ncustom.el\n\n#+begin_src emacs-lisp\n  (setq custom-file (expand-file-name \"~/.emacs.d/custom.el\"))\n  (load custom-file 'no-error 'no-message)\n#+end_src\n\n现在我们想将原本混合在一起的配置文件分为下面的几个模块（每一个模块为一个独立的配\n置文件并将其保存在指定的子目录中），它们分别是\n\n#+BEGIN_EXAMPLE\ninit-packages.el        # 插件管理\ninit-ui.el              # 视觉层配置\ninit-better-defaults.el # 增强内置功能\ninit-keybindings.el     # 快捷键绑定\ninit-org.el             # Org 模式相关的全部设定\ncustom.el              # 存放使用编辑器接口产生的配置信息\n#+END_EXAMPLE\n\n下面为将配置文件进行模块化后的目录结构，\n\n#+BEGIN_EXAMPLE\n├── init.el\n└── lisp\n    ├── custom.el\n    ├── init-better-defaults.el\n    ├── init-keybindings.el\n    ├── init-packages.el\n    ├── init-ui.el\n    └── init-org.el\n#+END_EXAMPLE\n\n使用模块化配置就可以让我们在之后的配置中迅速的定位与更改配置内容，让整个过程变得\n更有条理也更加高效。\n\n和之前一样 =init.el= 是配置文件的入口，现在它便成为了所有模块配置文件的入口，所\n以要使用这些模块时，我们需要在其中引用需要加载的模块。下面以 =init-packages.el=\n（此配置为添加插件的模块） 为例，详细说明如何模块化以及应用的方法。\n\n下面为 =~/.emacs.d/lisp/init-packages.el= 模块中的代码\n\n#+BEGIN_SRC emacs-lisp\n  (require 'package)\n  (setq package-archives '((\"gnu\"   . \"http://elpa.zilongshanren.com/gnu/\")\n\n                           (\"melpa\" . \"http://elpa.zilongshanren.com/melpa/\")))\n  (package-initialize)\n\n  ;;防止反复调用 package-refresh-contents 会影响加载速度\n  (when (not package-archive-contents)\n    (package-refresh-contents))\n\n  ;; 文件末尾\n  (provide 'init-packages)\n#+END_SRC\n\n下面为 =~/.emacs.d/init.el= 入口文件中的代码\n\n#+BEGIN_SRC emacs-lisp\n  (add-to-list 'load-path \"~/.emacs.d/lisp/\")\n\n  ;; Package Management\n  ;; -----------------------------------------------------------------\n  (require 'init-packages)\n#+END_SRC\n\n模块化要做的其实非常简单，我们要做的其实就是把某一个更改编辑器某定部分（例如，插\n件管理，显示层，快捷键绑定等）的配置代码写入一个独立的文件中并在末尾为其添加\n=(provide 'module-name)= (这里我们的模块名为 =init-packages= )使其可以在入口文件\n中被调用，然后再在入口文件中将其引用既可。\n\n这里需要注意的是，我们需要在入口文件中添加 =(add-to-list 'load-path\n\"~/.emacs.d/lisp/\")= 这可以让 Emacs 找到需要加载的模块所处的位置。\n\n这里推荐大家两个还不错的 Emacs 配置：\n\nhttps://github.com/condy0919/.emacs.d\n\nhttps://github.com/seagle0128/.emacs.d\n\n\n** 使用 Org 来管理配置文件\nOrg-mode 下的文学编程将颠覆你对于 Emacs 的看法。因为我们也可以使用 Org 来管理\nEmacs 的配置文件（本人其实更倾向于用多个文件来管理配置文件）。\n\n在 Org-mode 中你可以直接开启新的缓冲区（Buffer）直接用相应的 Major Mode 来编辑代码块内的内容。在代码块中使用 C-c ' 会直接打开对应模式的缓冲区（不仅限于 Lisp）。 这样就使在 Org-mode 中编辑代码变的十分方便快捷。\n\n使用 \u003cs 然后 Tab 可以直接插入代码块的代码片段（Snippet），更多类似的代码片段 （Org-mode Easy Templates）可以在这里找到。\n\n#+BEGIN_SRC emacs-lisp\n  (require 'org-tempo)  ;开启easy template\n\n  ;; 禁用左尖括号\n  (setq electric-pair-inhibit-predicate\n        `(lambda (c)\n           (if (char-equal c ?\\\u003c) t (,electric-pair-inhibit-predicate c))))\n\n  (add-hook 'org-mode-hook\n            (lambda ()\n              (setq-local electric-pair-inhibit-predicate\n                          `(lambda (c)\n                             (if (char-equal c ?\\\u003c) t (,electric-pair-inhibit-predicate c))))))\n#+END_SRC\n\n#+BEGIN_SRC emacs-lisp\n  ;; Your code goes here\n  ;; 你的代码写在这里\n#+END_SRC\n\n你需要将下面的代码放入配置入口文件（ =init.el= ）中，\n\n#+BEGIN_SRC emacs-lisp\n  (require 'org-install)\n  (require 'ob-tangle)\n  (org-babel-load-file (expand-file-name \"zilongshanren.org\" user-emacs-directory))\n#+END_SRC\n\n之后我们需要做的仅仅只是将所有的配置文件放入 Org 模式中的代码块即可，并使用目录\n结构来表述你的配置文件再把它保存在与入口文件相同的目录中即可（文件名为\n=org-file-name.org= ）。Emacs 会提取其中的配置并使其生效。这样做的好处是可以使自\n己和他人更直观的，理解你的配置文件或者代码。\n\n这里也给大家推荐一些使用 org-mode 进行配置管理的优秀范例：\n\nhttps://github.com/trev-dev/emacs\n\n* 第八天：macro 和 use-package\n\n视频地址如下\n- [[https://www.youtube.com/watch?v=j8Ietu_bMjE\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=9][Youtube]]\n- [[https://www.bilibili.com/video/BV1gF411j7VK/?vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n** 更好的默认设置\n\n在这一节我们会配置我们的编辑器使其有更好的使用体验。整个过程就如同搭积木一般，将\n更好的体验建立在已有的功能基础之上。这样的优化使整个过程变得更高效，也更有趣。\n\n下面的代码可以使 Emacs 自动加载外部修改过的文件。\n\n#+BEGIN_SRC emacs-lisp\n  (global-auto-revert-mode 1)\n#+END_SRC\n\n使用下面的代码可以关闭自动生产的保存文件（之前我们已经关闭过了 Emacs 自动生产的\n备份文件了，现在是关闭自动保存文件）。\n\n#+BEGIN_SRC emacs-lisp\n  (setq auto-save-default nil)\n#+END_SRC\n\n如果你发现你在使用中发现了那些编辑行为与你预期的不相符时，你可以通过搜索引擎去寻\n找解决方案然后将其加入你的配置中并打造一个真正属于你的神器！\n\n\n也许你并不喜欢听到错误时的“哔哔”的警告提示音，使用下面的代码你可以关闭 Emacs 中的警告音，\n\n#+BEGIN_SRC emacs-lisp\n  (setq ring-bell-function 'ignore)\n#+END_SRC\n\n每一次当 Emacs 需要与你确认某个命令时需要输入 =(yes or no)= 比较麻烦，所有我们可\n以使用下面的代码，设置一个别名将其简化为只输入 =(y or n)= 。\n\n#+BEGIN_SRC emacs-lisp\n  (fset 'yes-or-no-p 'y-or-n-p)\n#+END_SRC\n\n** Macro\n\n** 什么是宏\n#+begin_src emacs-lisp\n  (setq my-var 1)\n  (setq my-var (1+ my-var))\n\n  (defmacro inc (var)\n    (list 'setq var (list '1+ var)))\n\n  (macroexpand '(inc my-var))\n\n  (inc my-var)\n\n  ;;; pass by value\n  (defun inc-2 (var)\n    (setq var (1+ var)))\n\n\n  (inc-2 my-var)\n\n  ;; Backquote allows you to:\n\n  ;; quote a list, and\n  ;; selectively evaluate elements of the list (with comma ,), or:\n  ;; splice (eval \u0026 spread) the element with ,@\n\n  `(a list of ,(+ 2 3) elements)\n\n  (setq some-list '(2 3))\n\n  `(1 ,@some-list 4 ,@some-list)\n#+end_src\n\nBackquote：\n\nhttps://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote.html\n\n** Use-package\n   \n*** 安装 Use-package\n#+begin_src emacs-lisp\n  (package-install 'use-package) \n#+end_src\n\n*** 简介\n\nUse-package 是一个宏, 它能让你将一个包的 *require* 和它的相关的初始化等配置组织\n在一起, 避免对同一个包的配置代码散落在不同的文件中.\n\nUse-package 的更多信息参见以下地址: [[https://github.com/jwiegley/use-package][Use-package]]\n\n*** 一些简单的用法\n\n**** 更安全的 require\n\n在 Emacs 中, 当我们要引入一个包时, 通常会使用以下代码:\n\n#+BEGIN_SRC emacs-lisp\n  (require 'package-name)\n#+END_SRC\n\n但是当 *package-name* 不在 *load-path* 中时, 以上代码会抛出错误. 使用\n*Use-package* 可以避免:\n\n#+BEGIN_SRC emacs-lisp\n  (use-package package-name)\n#+END_SRC\n\n以上代码展开的结果如下:\n\n#+BEGIN_SRC emacs-lisp\n  (if\n      (not\n       (require 'package-name nil 't))\n      (ignore\n       (message\n        (format \"Cannot load %s\" 'package-name))))\n#+END_SRC\n\n可以看到, *Use-package* 使用 *ignore* 来避免抛出错误, 这样当某个包不存在时,\n*eamcs* 也能够正常启动.\n\n**** 将配置集中\n\n当我们引入某个包时, 有可能需要定义一些与这个包相关的变量, 使用 *Use-package* 实\n现这个需求如下:\n\n#+BEGIN_SRC emacs-lisp\n  (use-package package-name\n    :init\n    (setq my-var1 \"xxx\")\n    :config\n    (progn\n      (setq my-var2 \"xxx\")\n      (setq my-var3 \"xxx\")\n      )\n    )\n#+END_SRC\n\n在上例中, *init* 后的代码在包的 require 之前执行, 如果这段代码出错则跳过包的 require.\n\n*config* 后的代码在包的 require 之后执行.\n\n*init* 与 *config* 之后只能接单个表达式语句, 如果需要执行多个语句, 可以用 *progn* .\n\n**** autoload \n\n使用 require 时会引入这个包, 但是当你的包很多时会影响启动速度. 而使用 autoload\n则可以在真正需要这个包时再 require, 提高启动速度, 避免无谓的 require.\n\n使用 *Use-package* 可以轻松的实现这个功能:\n\n#+BEGIN_SRC emacs-lisp\n  (use-package package-name\n    :commands\n    (global-company-mode)\n    :defer t\n    )\n#+END_SRC\n\n使用 *commands* 可以让 package 延迟加载, 如以上代码会首先判断 package 的符号是否\n存在, 如果存在则在 *package-name* 的路径下加载. *defer* 也可以让 *package-name*\n进行延迟加载.\n\n**** 键绑定\n\n在之前的代码中, 如果我们需要绑定一个键, 需要使用 *global-key-bind* 或\n*define-key* 实现, 而使用*Use-package* 实现更简单:\n\n#+BEGIN_SRC emacs-lisp\n  (use-package company\n    :bind (:map company-active-map\n                (\"C-n\" . 'company-select-next)\n                (\"C-p\" . 'company-select-previous))\n    :init\n    (global-company-mode t)\n    :config\n    (setq company-minimum-prefix-length 1)\n    (setq company-idle-delay 0))\n#+END_SRC\n\n\n\n*** 为什么使用 Use-package\n\n1. Use-package 能让相关的配置更为集中, 避免配置分散带来的维护困难\n2. Use-package 有完善的错误处理, 使配置代码更为健壮\n3. Spacemacs，DoomEmacs  也大量使用了 Use-package\n\n* 第九天 Use-package 更多设置\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=X_sj5_5YiWk\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=11][Youtube]]\n- [[https://www.bilibili.com/video/BV1xv4y137vS/?vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n** Use-package 和更多默认设置\n\n*** 安装 restart-emacs \n#+begin_src emacs-lisp\n  (use-package restart-emacs\n    :ensure t)\n\n  ;;emacs --debug-init\n#+end_src\n\n删除 company 这个包, 看看会出现什么\n\n*** 自动安装 \n#+begin_src emacs-lisp\n  (require 'use-package-ensure)\n  (setq use-package-always-ensure t)\n\n  ;; Setup `use-package'\n  (unless (package-installed-p 'use-package)\n    (package-refresh-contents)\n    (package-install 'use-package))\n#+end_src\n这个选项会自动安装包，但是不会自动更新包到最新版本。\n- [ ] 清理所有的 package-install\n\n*** 保存光标历史，记住上个命令\n#+begin_src emacs-lisp\n  (use-package savehist\n    :ensure nil\n    :hook (after-init . savehist-mode)\n    :init (setq enable-recursive-minibuffers t ; Allow commands in minibuffers\n                history-length 1000\n                savehist-additional-variables '(mark-ring\n                                                global-mark-ring\n                                                search-ring\n                                                regexp-search-ring\n                                                extended-command-history)\n                savehist-autosave-interval 300)\n    )\n\n  (use-package saveplace\n    :ensure nil\n    :hook (after-init . save-place-mode))\n#+end_src\n\n*** 显示文件行、列、大小 ，美化状态栏\n#+begin_src emacs-lisp\n  (use-package simple\n    :ensure nil\n    :hook (after-init . size-indication-mode)\n    :init\n    (progn\n      (setq column-number-mode t)\n      ))\n\n  ;;modeline上显示我的所有的按键和执行的命令\n  (package-install 'keycast)\n  (add-to-list 'global-mode-string '(\"\" keycast-mode-line))\n  (keycast-mode t)\n\n  ;; 这里的执行顺序非常重要，doom-modeline-mode 的激活时机一定要在设置global-mode-string 之后‘\n  (use-package doom-modeline\n    :ensure t\n\n    :init\n    (doom-modeline-mode t))\n#+end_src\n\n\n* 第十天： orgmode 基础\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=nocgop6CHRI\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=12][Youtube]]\n- [[https://www.bilibili.com/video/BV1ES4y1B7Df/?spm_id_from=333.788\u0026vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n** org mode 简介\n*** 查看 orgmode 版本号\n\nC-h v org-version\n\n*** 安装最新版本\n#+begin_src emacs-lisp\n  ;; 安装org 之前，一定要配置 use-package 不使用内置的org 版本，可以使用本段代码最后面的代码，具体位置可以参考视频\n  (use-package org\n    :pin melpa\n    :ensure t)\n\n  (use-package org-contrib\n    :pin nongnu\n    )\n\n  ;; 添加新的 nongnu 的源\n  (\"nongnu\" . \"http://elpa.zilongshanren.com/nongnu/\")\n\n  ;;; 这个配置一定要配置在 use-package 的初始化之前，否则无法正常安装\n  (assq-delete-all 'org package--builtins)\n  (assq-delete-all 'org package--builtin-versions)\n#+end_src\n*** org todo \n#+begin_src emacs-lisp\n  (setq org-todo-keywords\n        (quote ((sequence \"TODO(t)\" \"STARTED(s)\" \"|\" \"DONE(d!/!)\")\n                (sequence \"WAITING(w@/!)\" \"SOMEDAY(S)\" \"|\" \"CANCELLED(c@/!)\" \"MEETING(m)\" \"PHONE(p)\"))))\n\n  ;;fix doom modeline\n  :custom-face\n  (mode-line ((t (:height 0.9))))\n  (mode-line-inactive ((t (:height 0.9))))\n\n  (require 'org-checklist)\n  ;; need repeat task and properties\n  (setq org-log-done t)\n  (setq org-log-into-drawer t)\n\n#+end_src\n*** org agenda\n#+begin_src emacs-lisp\n  ;; C-c C-s schedule\n  ;; C-c C-d deadline\n  (global-set-key (kbd \"C-c a\") 'org-agenda)\n  (setq org-agenda-files '(\"~/gtd.org\"))\n  (setq org-agenda-span 'day)\n#+end_src\n*** org capture\n#+begin_src emacs-lisp\n  (setq org-capture-templates\n        '((\"t\" \"Todo\" entry (file+headline \"~/gtd.org\" \"Workspace\")\n           \"* TODO [#B] %?\\n  %i\\n %U\"\n           :empty-lines 1)))\n\n  (global-set-key (kbd \"C-c r\") 'org-capture)\n#+end_src\n\n*** org effect\n在 agenda view 中, 按 e 键可以设置 effort, 按 _ 可以过滤指定 effort 的 heading\n\n*** org tags \n在 agenda view 中, 按 : 可以按照 tag 名称来过滤 todo 的 heading （tips: 这里快捷键都可以通过 M-x 来查看）\n\n*** org priority\nin agenda view ,\n#+begin_src emacs-lisp\n  (setq org-agenda-custom-commands\n        '((\"c\" \"重要且紧急的事\"\n           ((tags-todo \"+PRIORITY=\\\"A\\\"\")))\n          ;; ...other commands here\n          ))\n#+end_src\n\n** 参考资料\nhttps://www.cnblogs.com/Open_Source/archive/2011/07/17/2108747.html\n\n* 第十一天：使用 ox-hugo 来写博客\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=NWaiqi89tgk\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=14][Youtube]]\n- [[https://www.bilibili.com/video/BV1ZR4y1X7D7/?spm_id_from=333.788\u0026vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n使用 org mode 写博客，然后托管在 Github 上面，我们可以打造一个非常好用便捷且免费的写作系统。\n** 安装 hugo\n在 windows 上面安装 hugo 有多种方法，本文使用 chocolatey 包管理器。\n\n其他操作系统以及 windows 平台更多的安装方法参考以下链接：\nhttps://gohugo.io/getting-started/installing/\n\n*** 安卓 choco 包管理器\n使用 powershell 来安装（如果你的系统没有 powershell, 需要首先安装 powershell).\n\n使用管理员权限打开 powershell\n#+begin_src sh\n  Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))\n#+end_src\n\n安装完后，在 powershell 中输入 choco, 你会得到如下截图则说明安装成功：\n\n#+DOWNLOADED: screenshot @ 2022-10-16 20:36:02\n[[file:img/2022-10-16_20-36-02_screenshot.jpg]]\n\n*** 安装 hugo\n#+begin_src sh \n  choco install hugo --confirm\n#+end_src\n\n** 新建博客站点\n#+begin_src sh\n  hugo new site blog\n#+end_src\n\n使用 git 来管理你的博客系统：\n\n#+begin_src sh\n  cd blog \n  git init \n  git add .\n  git commit -m \"first commit\"\n#+end_src\n\n** 安装 hugo 主题 even\n我们使用 git submodule 来安装：\n#+begin_src sh\n  git submodule add https://github.com/olOwOlo/hugo-theme-even themes/even\n#+end_src\n\n** 测试站点\n\n拷贝 even 主题中的 examplesite 里面的内容到 testblog:\n\n在命令行中输入 hugo server, 此命令会自动生成博客内容到 public 目录，同时会在本地启动一个 http 服务器供我们来预览博客。\n关于 even 主题更多地使用请参考官方主页：\n\n**注意：** 如果要显示草稿内容，需要使用 `hugo server -D`\n\nhttps://github.com/olOwOlo/hugo-theme-even\n\n** 使用 org mode 来写博客\n\n首先我们需要安装 https://github.com/kaushalmodi/ox-hugo\n\n#+begin_src emacs-lisp\n  (use-package ox-hugo\n    :ensure t   ;Auto-install the package from Melpa\n    :pin melpa  ;`package-archives' should already have (\"melpa\" . \"https://melpa.org/packages/\")\n    :after ox)\n#+end_src\n\nox-hugo 有两种方式来写博客。\n- 每篇博客一个 org 文件\n- 每一个 org subtree 是一篇博客（这种是推荐的方式）\n\n使用 org capture 来新建博客：(注意 elisp 中 blog 文件的路径要替换成你自己的)\n\n#+begin_src emacs-lisp\n  (with-eval-after-load 'org-capture\n    (defun org-hugo-new-subtree-post-capture-template ()\n      \"Returns `org-capture' template string for new Hugo post.\n  See `org-capture-templates' for more information.\"\n      (let* ((title (read-from-minibuffer \"Post Title: \")) ;Prompt to enter the post title\n             (fname (org-hugo-slug title)))\n        (mapconcat #'identity\n                   `(\n                     ,(concat \"* TODO \" title)\n                     \":PROPERTIES:\"\n                     ,(concat \":EXPORT_FILE_NAME: \" fname)\n                     \":END:\"\n                     \"\\n\\n\")          ;Place the cursor here finally\n                   \"\\n\")))\n\n    (add-to-list 'org-capture-templates\n                 '(\"h\"                ;`org-capture' binding + h\n                   \"Hugo post\"\n                   entry\n                   ;; It is assumed that below file is present in `org-directory'\n                   ;; and that it has a \"Blog Ideas\" heading. It can even be a\n                   ;; symlink pointing to the actual location of all-posts.org!\n                   (file+headline \"c:/Users/lionqu/blog/all-blog.org\" \"Blog Ideas\")\n                   (function org-hugo-new-subtree-post-capture-template))))\n#+end_src\n\n配置 all-blog.org, 让它在保存内容的时候自动生成博客内容。\n\nhttps://ox-hugo.scripter.co/doc/auto-export-on-saving/\n\n** 配置 github 和 github workflow 来自动发布博客\n1. 新建一个 github 仓库\n2. 添加 remote 并 push 到远程\n3. 添加 github workflow\n\n* 第十二天： 使用 eglot 来编写、运行和调试 C/C++ 代码\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=6zN3RYwaHYY\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=16][Youtube]]\n- [[https://www.bilibili.com/video/BV1QF41197g7/?spm_id_from=333.788\u0026vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n** 安装 Emacs 29 （pretest 版本下载地址）\nhttps://alpha.gnu.org/gnu/emacs/pretest/windows/emacs-29/?C=M;O=D\n修复一个运行报错：\n#+begin_src emacs-lisp\n                                          ;  (global-linum-mode 1)\n  (global-display-line-numbers-mode t)    ;修改成这个来显示行号，性能更好\n#+end_src\n** 安装 mysys2\n1. 下载 https://www.msys2.org/\n2. 安装 C/C++ 必要的软件工具\n   #+begin_src  sh\n     pacman -Syu\n     pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-gdb make mingw-w64-x86_64-clang mingw-w64-x86_64-clang-tools-extra\n   #+end_src\n3. 设置环境变量\n   #+begin_src sh\n     C:\\msys64\\mingw64\\bin\n     C:\\msys64\\usr\\bin\n   #+end_src \n\n** 安装 eglot(Emacs 29 自带 eglot)\n#+begin_src emacs-lisp\n  (require 'eglot)\n  (add-to-list 'eglot-server-programs '((c++-mode c-mode) \"clangd\"))\n  (add-hook 'c-mode-hook #'eglot-ensure)\n  (add-hook 'c++-mode-hook #'eglot-ensure)\n#+end_src\n\n** 一键运行代码\n1. 安装 quickrun:\n   #+begin_src emacs-lisp\n     (use-package quickrun\n       :ensure t\n       :commands (quickrun)\n       :init\n       (quickrun-add-command \"c++/c1z\"\n         '((:command . \"g++\")\n           (:exec . (\"%c -std=c++1z %o -o %e %s\"\n                     \"%e %a\"))\n           (:remove . (\"%e\")))\n         :default \"c++\"))\n   #+end_src\n2. 自定义快捷键\n#+begin_src emacs-lisp\n  (global-set-key (kbd \"\u003cf5\u003e\") 'quickrun)\n#+end_src\n\n** 使用 gdb 调试\n1. 运行 M-x compile, 输入 g++ -g -o test.o test.cpp\n2. 使用 M-x gud-gdb  输入 gdb ./test.o\n3. 常用调试命令\n| name            | function                                           |\n|-----------------+----------------------------------------------------|\n| list            | 显示源代码                                           |\n| break           | 新增断点， break main, break 12（行号）               |\n| info            | 查看断点或者局部变量信息 info breakpoints, info locals |\n| run             | 开始调试                                             |\n| next            | 类似 step over                                       |\n| step            | 跳转到函数内部                                        |\n| continue        | 继续运行到下一个断点                                   |\n| quit            | 退出调试                                             |\n| watch           | 内存断点                                             |\n| display         | 类似 IDE 里面的 watch 功能                              |\n| break 11 if xxx | 条件断点                                               |\n\n* 第十三天：使用 Evil, 地球上最厉害的 vim 按键模拟\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=QqFaKyQ_pZ8\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=13][Youtube]]\n- [[https://www.bilibili.com/video/BV1T14y1X7CW/?spm_id_from=333.788\u0026vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n** 安装 Evil\n*** Install from melpa\n#+begin_src emacs-lisp\n\n  (use-package evil\n    :ensure t\n    :init\n    (setq evil-want-keybinding nil)\n    (setq evil-want-C-u-scroll t)\n    (evil-mode)\n\n    ;; https://emacs.stackexchange.com/questions/46371/how-can-i-get-ret-to-follow-org-mode-links-when-using-evil-mode\n    (with-eval-after-load 'evil-maps\n      (define-key evil-motion-state-map (kbd \"RET\") nil))\n    )\n#+end_src\n*** Install undo tree\n#+begin_src emacs-lisp\n  (use-package undo-tree\n    :diminish\n    :init\n    (global-undo-tree-mode 1)\n    (setq undo-tree-auto-save-history nil)\n    (evil-set-undo-system 'undo-tree))\n#+end_src\n** Modes and States\n*** Normal State  (N)\nThis is the default “resting state” of Evil, in which the main body of vi bindings are defined.\n*** Insert State (I)\nThis is the state for insertion of text, where non-modified keys will insert the corresponding character in the buffer.\n*** Emacs State  (E)\nA state that as closely as possible mimics default Emacs behaviour, by eliminating all vi bindings, except for C-z, to re-enter normal state.\n*** Visual State (V)\nA state for selecting text regions. Motions are available for modifying the selected region, and operators are available for acting on it.\n*** Motion State (M)\nA special state useful for buffers that are read-only, where motions are available but editing operations are not.\n*** Replace State (R)\nA special state mostly similar to insert state, except it replaces text instead of inserting.\n*** Operator-Pending State (O)\nA special state entered after launching an operator, but before specifying the corresponding motion or text object.\n** Evil 基础用法\n*** 增删改查 （text-obj, commands, replace ）\n*** 如果对 evil 不太熟悉，还可以使用这个插件来练习 evil 的使用： https://github.com/clsty/evil-tutor-sc\n** 自定义快捷键\n*** 定义不同 state 下面的快捷键\n#+begin_src emacs-lisp\n  (setcdr evil-insert-state-map nil)\n  (define-key evil-insert-state-map [escape] 'evil-normal-state)\n\n  (define-key evil-normal-state-map (kbd \"[ SPC\") (lambda () (interactive) (evil-insert-newline-above) (forward-line)))\n  (define-key evil-normal-state-map (kbd \"] SPC\") (lambda () (interactive) (evil-insert-newline-below) (forward-line -1)))\n\n  (define-key evil-normal-state-map (kbd \"[ b\") 'previous-buffer)\n  (define-key evil-normal-state-map (kbd \"] b\") 'next-buffer)\n  (define-key evil-motion-state-map (kbd \"[ b\") 'previous-buffer)\n  (define-key evil-motion-state-map (kbd \"] b\") 'next-buffer)\n\n  (evil-define-key 'normal dired-mode-map\n    (kbd \"\u003cRET\u003e\") 'dired-find-alternate-file\n    (kbd \"C-k\") 'dired-up-directory\n    \"`\" 'dired-open-term\n    \"o\" 'dired-find-file-other-window\n    \"s\" 'hydra-dired-quick-sort/body\n    \"z\" 'dired-get-size\n    \"!\" 'zilongshanren/do-shell-and-copy-to-kill-ring\n    \")\" 'dired-omit-mode)\n#+end_src\n*** spacemacs like 快捷键如何定义\n#+begin_src emacs-lisp\n\n  (use-package general\n    :init\n    (with-eval-after-load 'evil\n      (general-add-hook 'after-init-hook\n                        (lambda (\u0026rest _)\n                          (when-let ((messages-buffer (get-buffer \"*Messages*\")))\n                            (with-current-buffer messages-buffer\n                              (evil-normalize-keymaps))))\n                        nil\n                        nil\n                        t))\n\n\n    (general-create-definer global-definer\n      :keymaps 'override\n      :states '(insert emacs normal hybrid motion visual operator)\n      :prefix \"SPC\"\n      :non-normal-prefix \"C-SPC\")\n\n    (defmacro +general-global-menu! (name infix-key \u0026rest body)\n      \"Create a definer named +general-global-NAME wrapping global-definer.\n  Create prefix map: +general-global-NAME. Prefix bindings in BODY with INFIX-KEY.\"\n      (declare (indent 2))\n      `(progn\n         (general-create-definer ,(intern (concat \"+general-global-\" name))\n           :wrapping global-definer\n           :prefix-map ',(intern (concat \"+general-global-\" name \"-map\"))\n           :infix ,infix-key\n           :wk-full-keys nil\n           \"\" '(:ignore t :which-key ,name))\n         (,(intern (concat \"+general-global-\" name))\n          ,@body)))\n\n    (general-create-definer global-leader\n      :keymaps 'override\n      :states '(emacs normal hybrid motion visual operator)\n      :prefix \",\"\n      \"\" '(:ignore t :which-key (lambda (arg) `(,(cadr (split-string (car arg) \" \")) . ,(replace-regexp-in-string \"-mode$\" \"\" (symbol-name major-mode)))))))\n\n  (use-package general\n    :init\n    (global-definer\n      \"!\" 'shell-command\n      \"SPC\" 'execute-extended-command\n      \"'\" 'vertico-repeat\n      \"+\" 'text-scale-increase\n      \"-\" 'text-scale-decrease\n      \"u\" 'universal-argument\n      \"hdf\" 'describe-function\n      \"hdv\" 'describe-variable\n      \"hdk\" 'describe-key\n      )\n\n    (+general-global-menu! \"buffer\" \"b\"\n      \"d\" 'kill-current-buffer\n      \"b\" '(consult-buffer :which-key \"consult buffer\")\n      \"B\" 'switch-to-buffer\n      \"p\" 'previous-buffer\n      \"R\" 'rename-buffer\n      \"M\" '((lambda () (interactive) (switch-to-buffer \"*Messages*\"))\n            :which-key \"messages-buffer\")\n      \"n\" 'next-buffer\n      \"i\" 'ibuffer\n      \"f\" 'my-open-current-directory\n      \"k\" 'kill-buffer\n      \"y\" 'copy-buffer-name\n      \"K\" 'kill-other-buffers)\n#+end_src\n参考我的配置： https://github.com/zilongshanren/emacs.d/blob/eglot/lisp/init-keybindings.el\n** 相关插件列表（推荐我自己经常用的）\n*** evil-anzu\n#+begin_src emacs-lisp\n  (use-package evil-anzu\n    :ensure t\n    :after evil\n    :diminish\n    :demand t\n    :init\n    (global-anzu-mode t))\n#+end_src\n*** evil-collections\n#+begin_src emacs-lisp\n  (use-package evil-collection\n    :ensure t\n    :demand t\n    :config\n    (setq evil-collection-mode-list (remove 'lispy evil-collection-mode-list))\n    (evil-collection-init)\n\n    (cl-loop for (mode . state) in\n             '((org-agenda-mode . normal)\n               (Custom-mode . emacs)\n               (eshell-mode . emacs)\n               (makey-key-mode . motion))\n             do (evil-set-initial-state mode state))\n\n#+end_src\n*** evil-surround\n#+begin_src emacs-lisp\n  (use-package evil-surround\n    :ensure t\n    :init\n    (global-evil-surround-mode 1))\n#+end_src\n*** evil-nerd-commenter\n#+begin_src emacs-lisp\n  (use-package evil-nerd-commenter\n    :init\n    (define-key evil-normal-state-map (kbd \",/\") 'evilnc-comment-or-uncomment-lines)\n    (define-key evil-visual-state-map (kbd \",/\") 'evilnc-comment-or-uncomment-lines)\n    )\n#+end_src\n*** evil-snipe\n#+begin_src emacs-lisp\n  (use-package evil-snipe\n    :ensure t\n    :diminish\n    :init\n    (evil-snipe-mode +1)\n    (evil-snipe-override-mode +1))\n#+end_src\n*** evil-matchit\n#+begin_src emacs-lisp\n  (use-package evil-matchit\n    :ensure\n    :init\n    (global-evil-matchit-mode 1))\n#+end_src\n** 高阶用法（自定义 text-obj 或者 自定义 commands)\n1. https://github.com/noctuid/evil-guide#modes\n2. https://evil.readthedocs.io/en/latest/overview.html\n\n\n\n\n\n* 第十四天：精选 packages, 大大提升你的 Emacs 编辑效率\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=7hAqzTF1iRs\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=14][Youtube]]\n- [[https://www.bilibili.com/video/BV1zh4y1k7a5/?spm_id_from=333.788\u0026vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n** Some minor fix:\n#+begin_src emacs-lisp\n\n  ;; make c-j/c-k work in vertico selection\n  (define-key vertico-map (kbd \"C-j\") 'vertico-next)\n  (define-key vertico-map (kbd \"C-k\") 'vertico-previous)\n\n  ;; make consult-ripgrep work\n  (add-to-list 'process-coding-system-alist \n               '(\"[rR][gG]\" . (utf-8-dos . windows-1251-dos)))\n#+end_src\n** 多光标操作 iedit \u0026 evil-multiedit\n#+begin_src emacs-lisp\n  (use-package iedit\n    :ensure t\n    :init\n    (setq iedit-toggle-key-default nil)\n    :config\n    (define-key iedit-mode-keymap (kbd \"M-h\") 'iedit-restrict-function)\n    (define-key iedit-mode-keymap (kbd \"M-i\") 'iedit-restrict-current-line))\n\n  (use-package evil-multiedit\n    :ensure t\n    :commands (evil-multiedit-default-keybinds)\n    :init\n    (evil-multiedit-default-keybinds))\n#+end_src\n** expand-region\n#+begin_src emacs-lisp\n  (use-package expand-region\n    :config\n    (defadvice er/prepare-for-more-expansions-internal\n        (around helm-ag/prepare-for-more-expansions-internal activate)\n      ad-do-it\n      (let ((new-msg (concat (car ad-return-value)\n                             \", H to highlight in buffers\"\n                             \", / to search in project, \"\n                             \"e iedit mode in functions\"\n                             \"f to search in files, \"\n                             \"b to search in opened buffers\"))\n            (new-bindings (cdr ad-return-value)))\n        (cl-pushnew\n         '(\"H\" (lambda ()\n                 (interactive)\n                 (call-interactively\n                  'zilongshanren/highlight-dwim)))\n         new-bindings)\n        (cl-pushnew\n         '(\"/\" (lambda ()\n                 (interactive)\n                 (call-interactively\n                  'my/search-project-for-symbol-at-point)))\n         new-bindings)\n        (cl-pushnew\n         '(\"e\" (lambda ()\n                 (interactive)\n                 (call-interactively\n                  'evil-multiedit-match-all)))\n         new-bindings)\n        (cl-pushnew\n         '(\"f\" (lambda ()\n                 (interactive)\n                 (call-interactively\n                  'find-file)))\n         new-bindings)\n        (cl-pushnew\n         '(\"b\" (lambda ()\n                 (interactive)\n                 (call-interactively\n                  'consult-line)))\n         new-bindings)\n        (setq ad-return-value (cons new-msg new-bindings)))))\n#+end_src\n添加一个快捷键，让标记和搜索功能更方便：\n#+begin_src emacs-lisp\n\n  ;;;###autoload\n  (defun my/search-project-for-symbol-at-point ()\n    (interactive)\n    (if (use-region-p)\n        (progn\n          (consult-ripgrep (project-root (project-current))\n                           (buffer-substring (region-beginning) (region-end))))))\n\n  (global-definer\n    \"hc\" 'zilongshanren/clearn-highlight\n    \"hH\" 'zilongshanren/highlight-dwim\n    \"v\" 'er/expand-region\n    )\n#+end_src\n** interactive replace \n#+begin_src emacs-lisp\n  (defun zilongshanren/evil-quick-replace (beg end )\n    (interactive \"r\")\n    (when (evil-visual-state-p)\n      (evil-exit-visual-state)\n      (let ((selection (regexp-quote (buffer-substring-no-properties beg end))))\n        (setq command-string (format \"%%s /%s//g\" selection))\n        (minibuffer-with-setup-hook\n            (lambda () (backward-char 2))\n          (evil-ex command-string)))))\n\n  (define-key evil-visual-state-map (kbd \"C-r\") 'zilongshanren/evil-quick-replace)\n#+end_src\n** 安装 quelpa 插件\n#+begin_src emacs-lisp\n  (use-package quelpa)\n\n  (unless (package-installed-p 'quelpa-use-package)\n    (quelpa\n     '(quelpa-use-package\n       :fetcher git\n       :url \"https://github.com/quelpa/quelpa-use-package.git\")))\n\n  (use-package quelpa-use-package\n    :init\n    (setq quelpa-use-package-inhibit-loading-quelpa t)\n    :demand t)\n#+end_src\n** symbol-overlay \u0026 highlight-global\n#+begin_src emacs-lisp\n  (defun zilongshanren/highlight-dwim ()\n    (interactive)\n    (if (use-region-p)\n        (progn\n          (highlight-frame-toggle)\n          (deactivate-mark))\n      (symbol-overlay-put)))\n\n  (defun zilongshanren/clearn-highlight ()\n    (interactive)\n    (clear-highlight-frame)\n    (symbol-overlay-remove-all))\n\n  (use-package symbol-overlay\n    :config\n    (define-key symbol-overlay-map (kbd \"h\") 'nil))\n\n  (use-package highlight-global\n    :ensure nil\n    :commands (highlight-frame-toggle)\n    :quelpa (highlight-global :fetcher github :repo \"glen-dai/highlight-global\")\n    :config\n    (progn\n      (setq-default highlight-faces\n                    '(('hi-red-b . 0)\n                      ('hi-aquamarine . 0)\n                      ('hi-pink . 0)\n                      ('hi-blue-b . 0)))))\n#+end_src\n\n* 第十五天：使用 Treesit + eglot 来打造现代编程 IDE\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=Jzy9Au3CNFY\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=15][Youtube]]\n- [[https://www.bilibili.com/video/BV1W8411o7NM/?spm_id_from=333.788\u0026vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n** 正式版本 Emacs 29\nhttp://ftp.gnu.org/gnu/windows/emacs/emacs-29/\n** 安装 treesit-auto 插件\nhttps://github.com/renzmann/treesit-auto\n#+begin_src emacs-lisp\n  (use-package treesit-auto\n    :demand t\n    :config\n    (setq treesit-auto-install 'prompt)\n    (global-treesit-auto-mode))\n#+end_src\n** 配置 fontlock level\n#+begin_src emacs-lisp\n  (setq treesit-font-lock-level 4)\n#+end_src\n** 跳转函数列表 consult-imenu\n#+begin_src emacs-lisp\n  (+general-global-menu! \"search\" \"s\"\n    \"j\" 'consult-imenu\n    \"p\" 'consult-ripgrep\n    \"k\" 'consult-keep-lines\n    \"f\" 'consult-focus-lines)\n\n#+end_src\n** 查找定义和引用\n使用 ctrl-o 返回\n#+begin_src emacs-lisp\n  xref-find-references\n  xref-find-definitions\n#+end_src\n** 添加 snippets 支持\n#+begin_src emacs-lisp\n  (use-package yasnippet\n    :ensure t\n    :hook ((prog-mode . yas-minor-mode)\n           (org-mode . yas-minor-mode))\n    :init\n    :config\n    (progn\n      (setq hippie-expand-try-functions-list\n            '(yas/hippie-try-expand\n              try-complete-file-name-partially\n              try-expand-all-abbrevs\n              try-expand-dabbrev\n              try-expand-dabbrev-all-buffers\n              try-expand-dabbrev-from-kill\n              try-complete-lisp-symbol-partially\n              try-complete-lisp-symbol))))\n\n  (use-package yasnippet-snippets\n    :ensure t\n    :after yasnippet)\n#+end_src\n** 在头文件和源文件之间进行跳转\n#+begin_src emacs-lisp\n  ff-find-related-file\n#+end_src\n** 参考链接\n- https://github.com/emacs-mirror/emacs/blob/master/admin/notes/tree-sitter/starter-guide\n- https://www.masteringemacs.org/article/how-to-get-started-tree-sitter\n- https://mp.weixin.qq.com/s/kChdHIuh2ch9w5RiCHxo3w （Emacs 29 更新内容）\n- [[https://mp.weixin.qq.com/s?__biz=MzA4NDU1NTg2Ng==\u0026mid=2452309008\u0026idx=1\u0026sn=c5f822e36cc38e6d91683495e029adac\u0026chksm=883a8525bf4d0c336f6c1e3c9e2c934b751bd364f3e5565f9bb944b57a022b0d4aa6a5068146\u0026cur_album_id=1930972115608928260\u0026scene=189#wechat_redirect][Emacs Treesitter]]\n\n* 第十六天：窗口管理\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=nK6162fLsYM\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=16][Youtube]]\n- [[https://www.bilibili.com/video/BV15h4y1c71Z/?spm_id_from=333.788\u0026vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n** Evil 的窗口选择操作\n- C-w h/j/j/k\n** 推荐插件\n*** [[https://github.com/nschum/window-numbering.el][window numbering]]\n\n#+begin_src emacs-lisp\n(use-package window-numbering\n  :init\n  :hook (after-init . window-numbering-mode))\n#+end_src\n*** [[https://github.com/sabof/es-windows][es-windows]]\n\n#+begin_src emacs-lisp\n(use-package es-windows\n  :ensure t)\n#+end_src\n*** [[https://github.com/nschum/window-numbering.el][Buffer move]] \n\n#+begin_src emacs-lisp\n(use-package buffer-move\n  :ensure t)\n#+end_src\n*** [[https://github.com/dpsutton/resize-mode][Resize windows]] \n#+begin_src emacs-lisp\n(use-package resize-window\n  :ensure t\n  :init\n  (defvar resize-window-dispatch-alist\n    '((?n resize-window--enlarge-down \" Resize - Expand down\" t)\n      (?p resize-window--enlarge-up \" Resize - Expand up\" t)\n      (?f resize-window--enlarge-horizontally \" Resize - horizontally\" t)\n      (?b resize-window--shrink-horizontally \" Resize - shrink horizontally\" t)\n      (?r resize-window--reset-windows \" Resize - reset window layout\" nil)\n      (?w resize-window--cycle-window-positive \" Resize - cycle window\" nil)\n      (?W resize-window--cycle-window-negative \" Resize - cycle window\" nil)\n      (?2 split-window-below \" Split window horizontally\" nil)\n      (?3 split-window-right \" Slit window vertically\" nil)\n      (?0 resize-window--delete-window \" Delete window\" nil)\n      (?K resize-window--kill-other-windows \" Kill other windows (save state)\" nil)\n      (?y resize-window--restore-windows \" (when state) Restore window configuration\" nil)\n      (?? resize-window--display-menu \" Resize - display menu\" nil))\n    \"List of actions for `resize-window-dispatch-default.\nMain data structure of the dispatcher with the form:\n\\(char function documentation match-capitals\\)\"))\n#+end_src\n*** Winner (builtin)\n#+begin_src emacs-lisp\n(use-package winner\n  :ensure nil\n  :commands (winner-undo winner-redo)\n  :hook (after-init . winner-mode)\n  :init (setq winner-boring-buffers '(\"*Completions*\"\n                                      \"*Compile-Log*\"\n                                      \"*inferior-lisp*\"\n                                      \"*Fuzzy Completions*\"\n                                      \"*Apropos*\"\n                                      \"*Help*\"\n                                      \"*cvs*\"\n                                      \"*Buffer List*\"\n                                      \"*Ibuffer*\"\n                                      \"*esh command on file*\")))\n#+end_src\n*** [[https://github.com/karthink/popper][Popper]]\n#+begin_src emacs-lisp\n  (use-package popper\n    :defines popper-echo-dispatch-actions\n    :commands popper-group-by-directory\n    :bind (:map popper-mode-map\n                (\"s-`\" . popper-toggle-latest)\n                (\"s-o\"   . popper-cycle)\n                (\"M-`\" . popper-toggle-type))\n    :hook (emacs-startup . popper-mode)\n    :init\n    (setq popper-reference-buffers\n          '(\"\\\\*Messages\\\\*\"\n            \"Output\\\\*$\" \"\\\\*Pp Eval Output\\\\*$\"\n            \"\\\\*Compile-Log\\\\*\"\n            \"\\\\*Completions\\\\*\"\n            \"\\\\*Warnings\\\\*\"\n            \"\\\\*Flymake diagnostics.*\\\\*\"\n            \"\\\\*Async Shell Command\\\\*\"\n            \"\\\\*Apropos\\\\*\"\n            \"\\\\*Backtrace\\\\*\"\n            \"\\\\*prodigy\\\\*\"\n            \"\\\\*Calendar\\\\*\"\n            \"\\\\*Embark Actions\\\\*\"\n            \"\\\\*Finder\\\\*\"\n            \"\\\\*Kill Ring\\\\*\"\n            \"\\\\*Embark Export:.*\\\\*\"\n            \"\\\\*Edit Annotation.*\\\\*\"\n            \"\\\\*Flutter\\\\*\"\n            bookmark-bmenu-mode\n            lsp-bridge-ref-mode\n            comint-mode\n            compilation-mode\n            help-mode helpful-mode\n            tabulated-list-mode\n            Buffer-menu-mode\n            occur-mode\n            gnus-article-mode devdocs-mode\n            grep-mode occur-mode rg-mode deadgrep-mode ag-mode pt-mode\n            ivy-occur-mode ivy-occur-grep-mode\n            process-menu-mode list-environment-mode cargo-process-mode\n            youdao-dictionary-mode osx-dictionary-mode fanyi-mode\n\n            \"^\\\\*eshell.*\\\\*.*$\" eshell-mode\n            \"^\\\\*shell.*\\\\*.*$\"  shell-mode\n            \"^\\\\*terminal.*\\\\*.*$\" term-mode\n            \"^\\\\*vterm.*\\\\*.*$\"  vterm-mode\n\n            \"\\\\*DAP Templates\\\\*$\" dap-server-log-mode\n            \"\\\\*ELP Profiling Restuls\\\\*\" profiler-report-mode\n            \"\\\\*Flycheck errors\\\\*$\" \" \\\\*Flycheck checker\\\\*$\"\n            \"\\\\*Paradox Report\\\\*$\" \"\\\\*package update results\\\\*$\" \"\\\\*Package-Lint\\\\*$\"\n            \"\\\\*[Wo]*Man.*\\\\*$\"\n            \"\\\\*ert\\\\*$\" overseer-buffer-mode\n            \"\\\\*gud-debug\\\\*$\"\n            \"\\\\*lsp-help\\\\*$\" \"\\\\*lsp session\\\\*$\"\n            \"\\\\*quickrun\\\\*$\"\n            \"\\\\*tldr\\\\*$\"\n            \"\\\\*vc-.*\\\\*$\"\n            \"\\\\*eldoc\\\\*\"\n            \"^\\\\*elfeed-entry\\\\*$\"\n            \"^\\\\*macro expansion\\\\**\"\n\n            \"\\\\*Agenda Commands\\\\*\" \"\\\\*Org Select\\\\*\" \"\\\\*Capture\\\\*\" \"^CAPTURE-.*\\\\.org*\"\n            \"\\\\*Gofmt Errors\\\\*$\" \"\\\\*Go Test\\\\*$\" godoc-mode\n            \"\\\\*docker-containers\\\\*\" \"\\\\*docker-images\\\\*\" \"\\\\*docker-networks\\\\*\" \"\\\\*docker-volumes\\\\*\"\n            \"\\\\*prolog\\\\*\" inferior-python-mode inf-ruby-mode swift-repl-mode\n            \"\\\\*rustfmt\\\\*$\" rustic-compilation-mode rustic-cargo-clippy-mode\n            rustic-cargo-outdated-mode rustic-cargo-test-moed))\n\n    (when (display-grayscale-p)\n      (setq popper-mode-line\n            '(:eval\n              (concat\n               (propertize \" \" 'face 'mode-line-emphasis)\n               (all-the-icons-octicon \"pin\" :height 0.9 :v-adjust 0.0 :face 'mode-line-emphasis)\n               (propertize \" \" 'face 'mode-line-emphasis)))))\n\n    (setq popper-echo-dispatch-actions t)\n    (setq popper-group-function nil)\n    :config\n    (popper-echo-mode 1)\n\n    (with-no-warnings\n      (defun my-popper-fit-window-height (win)\n        \"Determine the height of popup window WIN by fitting it to the buffer's content.\"\n        (fit-window-to-buffer\n         win\n         (floor (frame-height) 3)\n         (floor (frame-height) 3)))\n      (setq popper-window-height #'my-popper-fit-window-height)\n\n      (defun popper-close-window-hack (\u0026rest _)\n        \"Close popper window via `C-g'.\"\n        ;; `C-g' can deactivate region\n        (when (and (called-interactively-p 'interactive)\n                   (not (region-active-p))\n                   popper-open-popup-alist)\n          (let ((window (caar popper-open-popup-alist)))\n            (when (window-live-p window)\n              (delete-window window)))))\n      (advice-add #'keyboard-quit :before #'popper-close-window-hack)))\n#+end_src\n** 按键绑定\n#+begin_src emacs-lisp\n  (global-definer\n    ;; 这里是其他的快捷键\n    \"0\" 'select-window-0\n    \"1\" 'select-window-1\n    \"2\" 'select-window-2\n    \"3\" 'select-window-3\n    \"4\" 'select-window-4\n    \"5\" 'select-window-5)\n\n  (+general-global-menu! \"window\" \"w\"\n    \"/\" 'split-window-right\n    \"-\" 'split-window-below\n    \"m\" 'delete-other-windows\n    \"u\" 'winner-undo\n    \"z\" 'winner-redo\n    \"w\" 'esw/select-window\n    \"s\" 'esw/swap-two-windows\n    \"d\" 'esw/delete-window\n    \"=\" 'balance-windows-area\n    \"r\" 'esw/move-window\n    \"x\" 'resize-window\n    \"H\" 'buf-move-left\n    \"L\" 'buf-move-right\n    \"J\" 'buf-move-down\n    \"K\" 'buf-move-up)\n#+end_src\n\n* 第十七天：工作区间管理\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=DDlgJe4HJNY\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=17][Youtube]]\n- [[https://www.bilibili.com/video/BV12p4y1J7Jx/?spm_id_from=333.788\u0026vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n** Awesome Tab 的问题\n偏爱使用 Emacs 内置 package\n** 使用内置的 tab-bar-mode\n#+begin_src emacs-lisp\n  (use-package tab-bar\n    :ensure nil\n    :init\n    (tab-bar-mode t)\n    (setq tab-bar-new-tab-choice \"*scratch*\") ;; buffer to show in new tabs\n    (setq tab-bar-close-button-show nil)      ;; hide tab close / X button\n    (setq tab-bar-show 1)                     ;; hide bar if \u003c= 1 tabs open\n    (setq tab-bar-format '(tab-bar-format-tabs tab-bar-separator))\n\n    (custom-set-faces\n     '(tab-bar ((t (:inherit mode-line))))\n     '(tab-bar-tab ((t (:inherit mode-line :foreground \"#993644\"))))\n     '(tab-bar-tab-inactive ((t (:inherit mode-line-inactive :foreground \"black\")))))\n\n    (defvar ct/circle-numbers-alist\n      '((0 . \"⓪\")\n        (1 . \"①\")\n        (2 . \"②\")\n        (3 . \"③\")\n        (4 . \"④\")\n        (5 . \"⑤\")\n        (6 . \"⑥\")\n        (7 . \"⑦\")\n        (8 . \"⑧\")\n        (9 . \"⑨\"))\n      \"Alist of integers to strings of circled unicode numbers.\")\n\n    (defun ct/tab-bar-tab-name-format-default (tab i)\n      (let ((current-p (eq (car tab) 'current-tab))\n            (tab-num (if (and tab-bar-tab-hints (\u003c i 10))\n                         (alist-get i ct/circle-numbers-alist) \"\")))\n        (propertize\n         (concat tab-num\n                 \" \"\n                 (alist-get 'name tab)\n                 (or (and tab-bar-close-button-show\n                          (not (eq tab-bar-close-button-show\n                                   (if current-p 'non-selected 'selected)))\n                          tab-bar-close-button)\n                     \"\")\n                 \" \")\n         'face (funcall tab-bar-tab-face-function tab))))\n    (setq tab-bar-tab-name-format-function #'ct/tab-bar-tab-name-format-default)\n    (setq tab-bar-tab-hints t))\n#+end_src\n** 工作区间\n#+begin_src emacs-lisp\n  (use-package tabspaces\n    ;; use this next line only if you also use straight, otherwise ignore it.\n    :hook (after-init . tabspaces-mode) ;; use this only if you want the minor-mode loaded at startup.\n    :commands (tabspaces-switch-or-create-workspace\n               tabspaces-open-or-create-project-and-workspace)\n    :custom\n    (tabspaces-use-filtered-buffers-as-default t)\n    (tabspaces-default-tab \"Default\")\n    (tabspaces-remove-to-default t)\n    (tabspaces-include-buffers '(\"*scratch*\"))\n    ;; maybe slow\n    (tabspaces-session t)\n    (tabspaces-session-auto-restore t)\n    :config\n    ;; Filter Buffers for Consult-Buffer\n\n    (with-eval-after-load 'consult\n      ;; hide full buffer list (still available with \"b\" prefix)\n      (consult-customize consult--source-buffer :hidden nil :default nil)\n      ;; set consult-workspace buffer list\n      (defvar consult--source-workspace\n        (list :name \"Workspace Buffers\"\n              :narrow ?w\n              :history 'buffer-name-history\n              :category 'buffer\n              :state #'consult--buffer-state\n              :default t\n              :items (lambda () (consult--buffer-query\n                                 :predicate #'tabspaces--local-buffer-p\n                                 :sort 'visibility\n                                 :as #'buffer-name)))\n\n        \"Set workspace buffer list for consult-buffer.\")\n      (add-to-list 'consult-buffer-sources 'consult--source-workspace)))\n#+end_src\n** 按键绑定\n#+begin_src emacs-lisp\n  (+general-global-menu! \"layout\" \"l\"\n    \"l\" 'tabspaces-switch-or-create-workspace\n    \"L\" 'tabspaces-restore-session\n    \"p\" 'tabspaces-open-or-create-project-and-workspace\n    \"f\" 'tabspaces-project-switch-project-open-file\n    \"s\" 'tabspaces-save-session\n    \"B\" 'tabspaces-switch-buffer-and-tab\n    \"b\" 'tabspaces-switch-to-buffer\n    \"R\" 'tab-rename\n    \"TAB\" 'tab-bar-switch-to-recent-tab\n    \"r\" 'tabspaces-remove-current-buffer\n    \"k\" 'tabspaces-close-workspace)\n#+end_src\n** 工作流介绍\n- 自动加载 workspace\n- 手动加载 workspace(减少启动时间)\n\n* 第十八天： Org-mode 进阶\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=onZfDDctl0Q\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=18][Youtube]]\n- [[https://www.bilibili.com/video/BV1oh4y1P73D/?spm_id_from=333.788\u0026vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n** Org Download\n*** how to install \n#+begin_src emacs-lisp\n(use-package org-download\n    :ensure t\n    :demand t\n    :after org\n    :config\n    (add-hook 'dired-mode-hook 'org-download-enable)\n    (setq org-download-screenshot-method \"powershell -c Add-Type -AssemblyName System.Windows.Forms;$image = [Windows.Forms.Clipboard]::GetImage();$image.Save('%s', [System.Drawing.Imaging.ImageFormat]::Png)\")\n    (defun org-download-annotate-default (link)\n      \"Annotate LINK with the time of download.\"\n      (make-string 0 ?\\s))\n\n    (setq-default org-download-heading-lvl nil\n                  org-download-image-dir \"./img\"\n                  ;; org-download-screenshot-method \"screencapture -i %s\"\n                  org-download-screenshot-file (expand-file-name \"screenshot.jpg\" temporary-file-directory)))\n#+end_src\n*** Change image size\n#+begin_src \n#+ATTR_HTML: :width 1000px\n#+end_src\n\nuse yasnippets\n** Org Protocol\n*** How to config\n**** 1. Step 1: Get emacsclient to work\n**** 2. 生成 org-protocol.reg\n#+begin_src sh\nWindows Registry Editor Version 5.00\n\n[HKEY_CLASSES_ROOT\\org-protocol]\n\"URL Protocol\"=\"\"\n@=\"URL:Org Protocol\"\n\n[HKEY_CLASSES_ROOT\\org-protocol\\shell]\n\n[HKEY_CLASSES_ROOT\\org-protocol\\shell\\open]\n\n[HKEY_CLASSES_ROOT\\org-protocol\\shell\\open\\command]\n@=\"\\\"C:\\\\Program Files\\\\Emacs\\\\emacs-29.1\\\\bin\\\\emacsclientw.exe\\\"  \\\"%1\\\"\"\n#+end_src\n**** 3. add org templates\n#+begin_src emacs-lisp\n  (setq org-agenda-file-note (expand-file-name \"~/notes.org\"))\n  (setq org-capture-templates\n        '(\n          (\"x\" \"Web Collections\" entry\n           (file+headline org-agenda-file-note \"Web\")\n           \"* %U %:annotation\\n\\n%:initial\\n\\n%?\")\n          ))\n#+end_src\n**** 4. add chrome bookmark \n#+begin_src sh\njavascript:location.href='org-protocol://capture?template=x\u0026url=%27+encodeURIComponent(location.href)+%27\u0026title=%27+encodeURIComponent(document.title)+%27\u0026body=%27+encodeURIComponent(function(){var html = \"\";var sel = window.getSelection();if (sel.rangeCount) {var container = document.createElement(\"div\");for (var i = 0, len = sel.rangeCount; i \u003c len; ++i) {container.appendChild(sel.getRangeAt(i).cloneContents());}html = container.innerHTML;}var dataDom = document.createElement(%27div%27);dataDom.innerHTML = html;dataDom.querySelectorAll(%27a%27).forEach(function(item, idx) {console.log(%27find a link%27);var url = new URL(item.href, window.location.href).href;var content = item.innerText;item.innerText = %27[[%27+url+%27][%27+content+%27]]%27;});[%27p%27, %27h1%27, %27h2%27, %27h3%27, %27h4%27].forEach(function(tag, idx){dataDom.querySelectorAll(tag).forEach(function(item, index) {var content = item.innerHTML.trim();if (content.length \u003e 0) {item.innerHTML = content + %27\u0026#13;\u0026#10;';}});});return dataDom.innerText.trim();}())\n#+end_src\n**** 6. return follow link \n#+begin_src emacs-lisp\n(org-return-follows-link t)\n#+end_src\n\n\n** Spell checking\n*** Install emacs packages\n#+begin_src emacs-lisp\n\n    (use-package flyspell-correct\n      :ensure t\n      :init)\n\n    (use-package ispell\n      :ensure nil\n      :init\n      (setq ispell-program-name \"aspell\")\n      (dolist (hook '(text-mode-hook))\n        (add-hook hook (lambda () (flyspell-mode 1))))\n      (setq ispell-personal-dictionary \"c:/msys64/mingw64/lib/aspell-0.60/en_GB\")\n  )\n\n      (define-key evil-insert-state-map (kbd \"C-;\") 'flyspell-correct-previous)\n\n#+end_src\n*** Install spell \n#+begin_src sh\npacman -S mingw64/mingw-w64-x86_64-aspell\npacman -S mingw64/mingw-w64-x86_64-aspell-en\n#+end_src\n*** Configuration \n1. add \"*C:\\msys64\\mingw64\\bin\" to  to PATH\n2. Error: The file \"c:\\msys64\\mingw64/lib/aspell-0.60/﻿en_US\" can not be opened for reading.\n\n** Fanyi Dictionary \n*** How to install \n#+begin_src emacs-lisp\n(use-package fanyi\n  :ensure t\n  :custom\n  (fanyi-providers '(;; 海词\n                     ;; fanyi-haici-provider\n                     ;; 有道同义词词典\n                     fanyi-youdao-thesaurus-provider\n                     ;; Etymonline\n                     fanyi-etymon-provider\n                     ;; Longman\n                     ;; fanyi-longman-provider)\n\t\t   )))\n#+end_src\n** Some useful keybindings\n#+begin_src emacs-lisp\n  C-RET  for creating new headlines\n  M-RET  for creating new lists\n  M-left/right/up/down\n#+end_src\n\n* 第十九天： Org Roam\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=M_DPLkiu3Gc\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=19][Youtube]]\n- [[https://www.bilibili.com/video/BV1uk4y1P7xr/?spm_id_from=333.788\u0026vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n** 安装 Org Oram\n在 HOME 新建一个 org 目录夹，用来存储你的 org roam 笔记。\n#+begin_src emacs-lisp\n  (use-package org-roam\n    :ensure t\n    :custom\n    (org-roam-directory (file-truename \"~/org\"))\n    :bind ((\"C-c n l\" . org-roam-buffer-toggle)\n           (\"C-c n f\" . org-roam-node-find)\n           (\"C-c n g\" . org-roam-graph)\n           (\"C-c n i\" . org-roam-node-insert)\n           (\"C-c n c\" . org-roam-capture)\n           ;; Dailies\n           (\"C-c n j\" . org-roam-dailies-capture-today))\n    :config\n    ;; If you're using a vertical completion framework, you might want a more informative completion interface\n    (setq org-roam-node-display-template (concat \"${title:*} \" (propertize \"${tags:10}\" 'face 'org-tag)))\n    (org-roam-db-autosync-mode)\n    ;; If using org-roam-protocol\n    (require 'org-roam-protocol))\n#+end_src\n** Org roam 基本使用\n*** 安装 corfu 来进行补全\n#+begin_src emacs-lisp\n(use-package corfu\n  :init\n  (progn\n    (setq corfu-auto t)\n    (setq corfu-cycle t)\n    (setq corfu-quit-at-boundary t)\n    (setq corfu-quit-no-match t)\n    (setq corfu-preview-current nil)\n    (setq corfu-min-width 80)\n    (setq corfu-max-width 100)\n    (setq corfu-auto-delay 0.2)\n    (setq corfu-auto-prefix 1)\n    (setq corfu-on-exact-match nil)\n    (global-corfu-mode)\n    ))\n#+end_src\n*** 新建笔记和查找笔记\nC-c n f\n*** 建立笔记引用\n[[]] \n*** 查找引用\norg-return-follows-link t\nc-c n l (org-roam-buffer-toggle)\n\n*** 已有的 headline 转换为一个节点\norg-id-get-create\nrefile node\n** 直接从 github 安装插件\n#+begin_src emacs-lisp\n(require 'cl-lib)\n(require 'use-package-core)\n\n(cl-defun slot/vc-install (\u0026key (fetcher \"github\") repo name rev backend)\n  (let* ((url (format \"https://www.%s.com/%s\" fetcher repo))\n         (iname (when name (intern name)))\n         (package-name (or iname (intern (file-name-base repo)))))\n    (unless (package-installed-p package-name)\n      (package-vc-install url iname rev backend))))\n\n(defvar package-vc-use-package-keyword :vc)\n\n(defun package-vc-use-package-set-keyword ()\n  (unless (member package-vc-use-package-keyword use-package-keywords)\n    (setq use-package-keywords\n          (let* ((pos (cl-position :unless use-package-keywords))\n                 (head (cl-subseq use-package-keywords 0 (+ 1 pos)))\n                 (tail (nthcdr (+ 1 pos) use-package-keywords)))\n            (append head (list package-vc-use-package-keyword) tail)))))\n\n(defun use-package-normalize/:vc (name-symbol keyword args)\n  (let ((arg (car args)))\n    (pcase arg\n      ((or `nil `t) (list name-symbol))\n      ((pred symbolp) args)\n      ((pred listp) (cond\n                     ((listp (car arg)) arg)\n                     ((string-match \"^:\" (symbol-name (car arg))) (cons name-symbol arg))\n                     ((symbolp (car arg)) args)))\n      (_ nil))))\n\n(defun use-package-handler/:vc (name-symbol keyword args rest state)\n  (let ((body (use-package-process-keywords name-symbol rest state)))\n    ;; This happens at macro expansion time, not when the expanded code is\n    ;; compiled or evaluated.\n    (if args\n        (use-package-concat\n         `((unless (package-installed-p ',(pcase (car args)\n                                            ((pred symbolp) (car args))\n                                            ((pred listp) (car (car args)))))\n             (apply #'slot/vc-install ',(cdr args))))\n         body)\n      body)))\n\n(defun package-vc-use-package-override-:ensure (func name-symbol keyword ensure rest state)\n  (let ((ensure (if (plist-member rest :vc)\n                    nil\n                  ensure)))\n    (funcall func name-symbol keyword ensure rest state)))\n\n(defun package-vc-use-package-activate-advice ()\n  (advice-add\n   'use-package-handler/:ensure\n   :around\n   #'package-vc-use-package-override-:ensure))\n\n(defun package-vc-use-package-deactivate-advice ()\n  (advice-remove\n   'use-package-handler/:ensure\n   #'package-vc-use-package-override-:ensure))\n\n;; register keyword on require\n(package-vc-use-package-set-keyword)\n#+end_src\n** Org roam UI\n#+begin_src emacs-lisp\n  (use-package org-roam-ui\n    :vc (:fetcher \"github\" :repo \"org-roam/org-roam-ui\"))\n#+end_src\n- 鼠标操作\n- 可视化\n- 实时显示链接\n\n\n* 第二十天：Emacs 配置问题排查\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=uuGrzmCwu7s\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=20][Youtube]]\n- [[https://www.bilibili.com/video/BV1Vz4y1j7LB/?spm_id_from=333.788\u0026vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n** 配置有问题，启动不了怎么办？\nemacs-debug --init\n** 不能安装包，提示签名错误\nFailed to verify signature archive-contents.sig\n\n#+begin_src emacs-lisp\n  (setq package-check-signature nil)\n#+end_src\n\n [[https://emacs-china.org/t/failed-to-verify-signature-archive-contents-sig/20508/5][Failed to verify signature archive-contents.sig - Emacs-general - Emacs China]]\n** a pax extended header, 包解压失败，可以使用 use-package :vc 直接安装\n使用 mysys2 的时候，系统会使用 unix 的 tar 去解压会有问题\nwindows 上面需要使用 system32/tar 这个程序去解压。\n#+begin_src emacs-lisp\n解决办法可以是 mv /usr/bin/tar /usr/bin/tarbak\n#+end_src\n** 上 Emacs China! 上 Emacs China! 上 Emacs China! （重要的事情说 3 遍）\n\n* 第二十一天： 优化性能，借鉴其他人的配置\n\n视频地址如下:\n- [[https://www.youtube.com/watch?v=Va9lcfsVKgU\u0026list=PLZx9tb9Niew-CXp_C0LfiJo-SpsQBVBq2\u0026index=21][Youtube]]\n- [[https://www.bilibili.com/video/BV1Ah4y1N7Kb/?spm_id_from=333.788\u0026vd_source=341db5d3a9324a7e00c10cbce0022a91][Bilibili]]\n\n** how to Profile performace\n** 怎么度量启动性能\n#+begin_src emacs-lisp\n(use-package benchmark-init\n  :ensure t\n  :demand t\n  :config\n  ;; To disable collection of benchmark data after init is done.\n  (add-hook 'after-init-hook 'benchmark-init/deactivate))\n#+end_src\n** use-package 哪些操作可以优化性能\nhttps://systemcrafters.net/emacs-from-scratch/cut-start-up-time-in-half/\n** 借鉴大佬的配置，作为框架\n*** 社区配置\nSpacemacs \u0026 DoomEmacs \n\n*** 个人配置\n- https://github.com/purcell/emacs.d\n- https://github.com/bbatsov/prelude\n- https://github.com/bbatsov/prelude\n- https://github.com/seagle0128/.emacs.d\n- https://github.com/zilongshanren/emacs.d （子龙山人）\n\n** 小技巧：\n#+begin_src emacs-lisp\n(defun spacemacs/alternate-buffer (\u0026optional window)\n  \"Switch back and forth between current and last buffer in the\ncurrent window.\nIf `spacemacs-layouts-restrict-spc-tab' is `t' then this only switches between\nthe current layouts buffers.\"\n  (interactive)\n  (cl-destructuring-bind (buf start pos)\n      (if (bound-and-true-p spacemacs-layouts-restrict-spc-tab)\n          (let ((buffer-list (persp-buffer-list))\n                (my-buffer (window-buffer window)))\n            ;; find buffer of the same persp in window\n            (seq-find (lambda (it) ;; predicate\n                        (and (not (eq (car it) my-buffer))\n                             (member (car it) buffer-list)))\n                      (window-prev-buffers)\n                      ;; default if found none\n                      (list nil nil nil)))\n        (or (cl-find (window-buffer window) (window-prev-buffers)\n                     :key #'car :test-not #'eq)\n            (list (other-buffer) nil nil)))\n    (if (not buf)\n        (message \"Last buffer not found.\")\n      (set-window-buffer-start-and-point window buf start pos))))\n#+end_src\n按键绑定：\n#+begin_src emacs-lisp\n    \"TAB\" 'spacemacs/alternate-buffer\n#+end_src\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femacs-china%2FSpacemacs-rocks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femacs-china%2FSpacemacs-rocks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femacs-china%2FSpacemacs-rocks/lists"}