<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tools on pemako</title><link>http://pemako.cn/blog/tools/</link><description>Recent content in Tools on pemako</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Thu, 09 Apr 2026 20:00:00 +0800</lastBuildDate><atom:link href="http://pemako.cn/blog/tools/index.xml" rel="self" type="application/rss+xml"/><item><title>Android 逆向</title><link>http://pemako.cn/blog/tools/android-reverse/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/tools/android-reverse/</guid><description>&lt;ol&gt;
&lt;li&gt;download tools
&lt;ol&gt;
&lt;li&gt;[[apktool]]&lt;/li&gt;
&lt;li&gt;[[dex2jar]]&lt;/li&gt;
&lt;li&gt;[[java-decompiler-gui]]&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;download apk
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;eg: com.baidu.tieba_mini_123205.apk&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;decompile
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;apktool d com.baidu.tieba_mini_123205.apk&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mv com.baidu.tieba_mini_123205.apk com.baidu.tieba_mini_123205.zip&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;unzip com.baidu.tieba_mini_123205.zip&lt;/code&gt; got &lt;code&gt;classes.dex&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mv classes.dex dex2jar-you-version-dir/&lt;/code&gt; and &lt;code&gt;d2j-dex2jar.sh classes.dex&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;use [[java-decompiler-gui]] open classes-dex2jar.jar&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="quick-check"&gt;
 Quick Check
 &lt;a class="anchor" href="#quick-check"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Is at least Java 1.8 installed?&lt;/li&gt;
&lt;li&gt;Does executing java -version on command line / command prompt return 1.8 or greater?&lt;/li&gt;
&lt;li&gt;If not, please install Java 8+ and make it the default. (Java 7 will also work at this time)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="installation-for-apktool"&gt;
 Installation for Apktool
 &lt;a class="anchor" href="#installation-for-apktool"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt;:&lt;/p&gt;</description></item><item><title>Asciinema</title><link>http://pemako.cn/blog/tools/asciinema/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/tools/asciinema/</guid><description>&lt;h2 id="how-it-works"&gt;
 How it works
 &lt;a class="anchor" href="#how-it-works"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;asciinema project is built of several complementary pieces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;command-line based terminal session recorder, &lt;code&gt;asciinema&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;website with an API at asciinema.org,&lt;/li&gt;
&lt;li&gt;javascript player&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you run &lt;code&gt;asciinema rec&lt;/code&gt; in your terminal the recording starts, capturing all output that is being printed to your terminal while you’re issuing the shell commands. When the recording finishes (by hitting Ctrl-D or typing &lt;code&gt;exit&lt;/code&gt;) then the captured output is uploaded to asciinema.org website and prepared for playback on the web.&lt;/p&gt;</description></item><item><title>Emacs</title><link>http://pemako.cn/blog/tools/emacs/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/tools/emacs/</guid><description>&lt;blockquote&gt;
&lt;p&gt;参考 &lt;a href="https://book1.emacs-china.org/#org67dd896"&gt;https://book1.emacs-china.org/#org67dd896&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="光标移动"&gt;
 光标移动
 &lt;a class="anchor" href="#%e5%85%89%e6%a0%87%e7%a7%bb%e5%8a%a8"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-f&lt;/code&gt; 向右移动一个字符，&lt;code&gt;f&lt;/code&gt; 代表 &lt;code&gt;forward&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-b&lt;/code&gt; 向左移动一个字符，&lt;code&gt;b&lt;/code&gt; 代表 &lt;code&gt;backward&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-p&lt;/code&gt; 移动到上一行 &lt;code&gt;p&lt;/code&gt; 代表 &lt;code&gt;previous&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-n&lt;/code&gt; 移动到下一行 &lt;code&gt;n&lt;/code&gt; 代表 &lt;code&gt;next&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-a&lt;/code&gt; 移动到行首 &lt;code&gt;a&lt;/code&gt; 代表 &lt;code&gt;ahead&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-e&lt;/code&gt; 移动到行尾 &lt;code&gt;e&lt;/code&gt; 代表 &lt;code&gt;end&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-v&lt;/code&gt; 移动到下一屏&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-l&lt;/code&gt; 重绘屏幕，并将光标所在的行置于屏幕的中央&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-a&lt;/code&gt; 移动到句首&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-e&lt;/code&gt; 移动到句尾&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-b&lt;/code&gt; 光标移动到下一个词（这里的词指英文单词，对于中文来说，则是移动到下一个标点符号）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-f&lt;/code&gt; 光标移动到前一个词&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-v&lt;/code&gt; 移动到上一屏&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-&amp;lt;&lt;/code&gt; 将光标移动到所有文字的最开头&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-&amp;gt;&lt;/code&gt; 将光标移动到所有文字的最末尾&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-u 数字 命令&lt;/code&gt; 表示这些数字参数的作用是指定命令的重复次数， 也被称为前缀参数
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-u 8 C-f&lt;/code&gt; 会向前移动 8 个字符&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;通常惯例, &lt;code&gt;Meta&lt;/code&gt; 系组合键用来操作 &amp;ldquo;由语言定义的单位（如词，句子，段落）&amp;quot;，而 &lt;code&gt;CONTROL&lt;/code&gt; 系列组合键用来操作 &amp;ldquo;与语言无关的基本单位（比如字符, 行等）&amp;quot;。&lt;/p&gt;
&lt;h3 id="退出-emacs"&gt;
 退出 Emacs
 &lt;a class="anchor" href="#%e9%80%80%e5%87%ba-emacs"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-x C-c&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="窗格-windows"&gt;
 窗格 &lt;code&gt;Windows&lt;/code&gt;
 &lt;a class="anchor" href="#%e7%aa%97%e6%a0%bc-windows"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-x 1&lt;/code&gt; 只保留一个窗格（也就是关闭掉其它所有窗格）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-x 2&lt;/code&gt; 上下打开两个窗格&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-x 3&lt;/code&gt; 左右打开两个窗格&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-x o&lt;/code&gt; 将光标移动到另一个窗格(&lt;code&gt;other&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-M-v&lt;/code&gt; 在一个窗格中编辑，使用 &lt;code&gt;C-M-v&lt;/code&gt; 命令滚动另外一个窗格中的文字&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="多窗口-multiple-frames"&gt;
 多窗口 Multiple Frames
 &lt;a class="anchor" href="#%e5%a4%9a%e7%aa%97%e5%8f%a3-multiple-frames"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;M-x make-frame&lt;/code&gt; 开启一个新的窗口&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-x delete-frame&lt;/code&gt; 关闭选中的窗口&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="插入与删除"&gt;
 插入与删除
 &lt;a class="anchor" href="#%e6%8f%92%e5%85%a5%e4%b8%8e%e5%88%a0%e9%99%a4"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;DEL&amp;gt;&lt;/code&gt; 删除光标前的一个字符&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-d&lt;/code&gt; 删除光标后的一个字符&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-&amp;lt;DEL&amp;gt;&lt;/code&gt; 删除光标前的一个词&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-d&lt;/code&gt; 删除光标后的一个词&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-k&lt;/code&gt; 移除从光标到行尾间的字符&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-k&lt;/code&gt; 移除从光标到句尾间的字符&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-y&lt;/code&gt; 召回最近一次移除的内容&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-y&lt;/code&gt; 每按一次召回前一次的内容&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="撤销-undo"&gt;
 撤销 Undo
 &lt;a class="anchor" href="#%e6%92%a4%e9%94%80-undo"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-/&lt;/code&gt; 如果修改了一段文字，又觉得改的不好，可以用 &lt;code&gt;undo&lt;/code&gt; 命令进行撤销；如果连续多次的使用, 则会把以前的命令也依次撤销&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-x u&lt;/code&gt; 撤销&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="文件"&gt;
 文件
 &lt;a class="anchor" href="#%e6%96%87%e4%bb%b6"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-x C-f&lt;/code&gt; 查找文件&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-x C-s&lt;/code&gt; 保存文件&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-x customize-variable make-backup-files&lt;/code&gt; 关掉文件备份&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="缓冲区-buffer"&gt;
 缓冲区 Buffer
 &lt;a class="anchor" href="#%e7%bc%93%e5%86%b2%e5%8c%ba-buffer"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-x C-b&lt;/code&gt; 列出缓冲区&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-x b buffername&lt;/code&gt; 切换到指定名称的缓冲区&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-x s&lt;/code&gt; 保存多个缓冲区（会找到所有已被修改但尚未存盘的缓冲区，然后逐个询问是否存盘）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="命令集扩展-extending-the-command-set"&gt;
 命令集扩展 Extending The Command Set
 &lt;a class="anchor" href="#%e5%91%bd%e4%bb%a4%e9%9b%86%e6%89%a9%e5%b1%95-extending-the-command-set"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-x&lt;/code&gt; 字符扩展 &lt;code&gt;C-x&lt;/code&gt; 之后输入另一个字符或者组合键&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-x&lt;/code&gt; 命令名扩展 &lt;code&gt;M-x&lt;/code&gt; 之后输入一个命令名&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="自动保存-auto-save"&gt;
 自动保存 Auto Save
 &lt;a class="anchor" href="#%e8%87%aa%e5%8a%a8%e4%bf%9d%e5%ad%98-auto-save"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Emacs&lt;/code&gt; 会定期将正在编辑的文件写入一个 &amp;ldquo;自动保存&amp;quot;文件中。自动保存文件的文件名的头尾各有一个 &lt;code&gt;#&lt;/code&gt; 字符，比如你正在编辑的文件叫 &lt;code&gt;hello.c&lt;/code&gt;, 那么它的自动保存文件就叫 &lt;code&gt;#hello.c#&lt;/code&gt;. 这个文件会在正常存盘之后被 &lt;code&gt;Emacs&lt;/code&gt; 删除。可以使用 &lt;code&gt;M-x recover file&lt;/code&gt; 来恢复你的自动保存文件。&lt;/p&gt;</description></item><item><title>Git</title><link>http://pemako.cn/blog/tools/git/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/tools/git/</guid><description>&lt;h2 id="rebase-使用"&gt;
 rebase 使用
 &lt;a class="anchor" href="#rebase-%e4%bd%bf%e7%94%a8"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://juejin.cn/post/6844903895160881166"&gt;https://juejin.cn/post/6844903895160881166&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;场景说明：&lt;/p&gt;
&lt;p&gt;A B两个同学同时开发，A修改了 one.md 文件并提交； B 这边没有pull直接修改了 two.md 文件然后提交，提示需要pull下来，这里采用 git pull &amp;ndash;rebase 的话生成的log为线性的
&lt;img src="https://raw.githubusercontent.com/pemako/imgs/master/public/20210720100053.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;A 再次修改提交，需要pull同步分支变更；这里不用rebase的情况下产生的log为下面情形。
&lt;img src="https://raw.githubusercontent.com/pemako/imgs/master/public/20210720100353.png" alt="" /&gt;&lt;/p&gt;
&lt;h2 id="多帐号配置"&gt;
 多帐号配置
 &lt;a class="anchor" href="#%e5%a4%9a%e5%b8%90%e5%8f%b7%e9%85%8d%e7%bd%ae"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;进入 &lt;code&gt;~/.ssh&lt;/code&gt; 目录下依次使用命令生成对应的秘钥文件
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ssh-keygen -t rsa -C &amp;quot;makosonm@gmail.com&amp;quot;&lt;/code&gt; 命名为 &lt;code&gt;id_rsa_makosonm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ssh-keygen -t rsa -C &amp;quot;pemako@gmail.com&amp;quot;&lt;/code&gt; 命名为 &lt;code&gt;id_rsa_pemako&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;在 github.com 的setting上添加对应的 &lt;code&gt;id_rsa_xx.pub&lt;/code&gt;文件内容到 SSH KEY&lt;/li&gt;
&lt;li&gt;在 &lt;code&gt;~/.ssh/config&lt;/code&gt; 文件中添加如内容&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Host makosonm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HostName github.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; User makosonm@gmail.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IdentityFile ~/.ssh/id_rsa_makosonm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Host pemako
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HostName github.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; User pemakoa@gmail.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IdentityFile ~/.ssh/id_rsa_pemako
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;不配置 global 的 user email 可以在不同的仓库配置不同的账号进行提交代码&lt;/p&gt;</description></item><item><title>Graphviz</title><link>http://pemako.cn/blog/tools/graphviz/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/tools/graphviz/</guid><description>&lt;h1 id="关于graphviz"&gt;
 关于Graphviz
 &lt;a class="anchor" href="#%e5%85%b3%e4%ba%8egraphviz"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;h2 id="11-简介"&gt;
 1.1 简介
 &lt;a class="anchor" href="#11-%e7%ae%80%e4%bb%8b"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Graphviz （英文：Graph Visualization Software的缩写）是一个由&lt;code&gt;AT&amp;amp;T实验室&lt;/code&gt;启动的开源工具包，可以用于绘制&lt;code&gt;DOT语言&lt;/code&gt;脚本描述的图形。它也提供了供其它软件使用的库。Graphviz是一个&lt;code&gt;自由软件&lt;/code&gt;，其授权为&lt;code&gt;Eclipse Public License&lt;/code&gt;。其Mac版本曾经获得2004年的&lt;code&gt;苹果设计奖&lt;/code&gt;[2]。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Graphviz由一种被称为DOT语言的图形描述语言[3] 与一组可以生成和/或处理DOT文件的工具组成：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;命令&lt;/th&gt;
 &lt;th&gt;说明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;dot&lt;/td&gt;
 &lt;td&gt;一个用来将生成的图形转换成多种输出格式的命令行工具。其输出格式包括PostScript，PDF，SVG，PNG，含注解的文本等等。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;neato&lt;/td&gt;
 &lt;td&gt;用于sprint model的生成（在Mac OS版本中称为energy minimized）。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;twopi&lt;/td&gt;
 &lt;td&gt;用于放射状图形的生成&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;circo&lt;/td&gt;
 &lt;td&gt;用于圆形图形的生成。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;fdp&lt;/td&gt;
 &lt;td&gt;另一个用于生成无向图的工具。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;dotty&lt;/td&gt;
 &lt;td&gt;一个用于可视化与修改图形的图形用户界面程序。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;lefty&lt;/td&gt;
 &lt;td&gt;一个可编程的(使用一种被EZ影响的语言[4])控件，它可以显示DOT图形，并允许用户用鼠标在图上执行操作。Lefty可以作为MVC模型的使用图形的GUI程序中的视图部分。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;官网：&lt;code&gt;http://www.graphviz.org/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;官方文档：&lt;code&gt;http://www.graphviz.org/Documentation.php&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;下载地址：&lt;code&gt;http://www.graphviz.org/Download.php&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="12-dot语言"&gt;
 1.2 DOT语言
 &lt;a class="anchor" href="#12-dot%e8%af%ad%e8%a8%80"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;DOT语言是一种文本图形描述语言它提供了一种简单的描述图形的方法，并且可以为人类和计算机程序所理解。DOT语言文件通常是具有&lt;code&gt;.gv&lt;/code&gt;或是&lt;code&gt;.dot&lt;/code&gt;的文件扩展名。很多程序都可以处理DOT文件。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="13-安装"&gt;
 1.3 安装
 &lt;a class="anchor" href="#13-%e5%ae%89%e8%a3%85"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Mac下直接通过&lt;code&gt;brew install graphviz&lt;/code&gt;了，也可以直接从官网下载; 注意最新的brew仓库中不再支持 mac10.13版本，这里需要进行编译安装。参考 &lt;a href="https://graphviz.org/download/"&gt;https://graphviz.org/download/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="14-简单示例"&gt;
 1.4 简单示例
 &lt;a class="anchor" href="#14-%e7%ae%80%e5%8d%95%e7%a4%ba%e4%be%8b"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Graphviz画图只需要两步。第一步创建文本文件并命令为x.dot，输入以下内容：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;graph demo {
 &amp;#34;Browser&amp;#34; -- {&amp;#34;Chrome&amp;#34;, &amp;#34;Fiefox&amp;#34;, &amp;#34;Safari&amp;#34;, &amp;#34;...&amp;#34;}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;第二步，使用命令将文本内容转换为图片。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;dot demo.dot -T png -o demo.png
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;-T&lt;/code&gt;表示输出类型，可以指定jpg、gif、svg等等，&lt;code&gt;-o&lt;/code&gt;指定输出文件名，不指定则输出到标准输出上。执行上面命令后不出意外则可以看到如下效果。&lt;/p&gt;</description></item><item><title>M4 宏处理器</title><link>http://pemako.cn/blog/tools/m4/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/tools/m4/</guid><description>&lt;h2 id="一m4-是什么"&gt;
 &lt;strong&gt;一、m4 是什么？&lt;/strong&gt;
 &lt;a class="anchor" href="#%e4%b8%80m4-%e6%98%af%e4%bb%80%e4%b9%88"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.gnu.org/software/m4/manual/m4.pdf"&gt;&lt;code&gt;GUN m4&lt;/code&gt;&lt;/a&gt; 是一种通用的 &lt;strong&gt;宏处理器（macro processor）&lt;/strong&gt;，最初是 Unix 标准工具的一部分，后来 GNU 也实现了自己的版本（GNU m4）。
它的名字来自 “macro”，设计思想和 C 语言的预处理器（cpp）类似，但更通用、可编程、与语言无关。&lt;/p&gt;
&lt;h3 id="-简单理解"&gt;
 &lt;strong&gt;🔧 简单理解：&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e7%ae%80%e5%8d%95%e7%90%86%e8%a7%a3"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;m4 是一个「文本宏展开器」：
它读入文本 → 按定义替换宏 → 输出展开后的文本。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;但 m4 比 C 预处理器灵活得多——它本身是一种“小型解释语言”，带有：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;宏定义&lt;/strong&gt;与展开机制；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;条件判断&lt;/strong&gt;（ifdef, ifelse）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;循环、递归&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;参数替换、字符串操作、文件包含&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可生成任意文本（代码、配置、脚本）&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="二m4-解决了什么问题"&gt;
 &lt;strong&gt;二、m4 解决了什么问题？&lt;/strong&gt;
 &lt;a class="anchor" href="#%e4%ba%8cm4-%e8%a7%a3%e5%86%b3%e4%ba%86%e4%bb%80%e4%b9%88%e9%97%ae%e9%a2%98"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;在 1970–80 年代，Unix 世界里还没有复杂的模板引擎、元编程机制，很多项目要面对：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;各种 &lt;strong&gt;平台差异&lt;/strong&gt;（操作系统、编译器特性不同）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;重复性代码生成&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配置文件或源代码模板&lt;/strong&gt; 需要根据条件生成；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;轻量级宏系统&lt;/strong&gt; 需要在编译前阶段运行。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;m4 的出现正是为了在「正式编译前」进行灵活的文本层面元编程。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="三历史上最典型的用途"&gt;
 &lt;strong&gt;三、历史上最典型的用途&lt;/strong&gt;
 &lt;a class="anchor" href="#%e4%b8%89%e5%8e%86%e5%8f%b2%e4%b8%8a%e6%9c%80%e5%85%b8%e5%9e%8b%e7%9a%84%e7%94%a8%e9%80%94"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="1-autoconf-系统的基础"&gt;
 &lt;strong&gt;1️⃣ autoconf 系统的基础&lt;/strong&gt;
 &lt;a class="anchor" href="#1-autoconf-%e7%b3%bb%e7%bb%9f%e7%9a%84%e5%9f%ba%e7%a1%80"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;这是 m4 最著名的应用场景。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GNU 的 autoconf（用于生成 configure 脚本）本质上就是一堆 .m4 宏定义。&lt;/li&gt;
&lt;li&gt;configure.ac 文件会通过 autoconf → m4 → 生成最终的 configure。&lt;/li&gt;
&lt;li&gt;它负责检测系统特性、生成 Makefile、适配不同环境。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;没有 m4，就没有 autoconf。&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Mac 使用技巧</title><link>http://pemako.cn/blog/tools/mac-usage/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/tools/mac-usage/</guid><description>&lt;h2 id="mac上的一些操作"&gt;
 mac上的一些操作
 &lt;a class="anchor" href="#mac%e4%b8%8a%e7%9a%84%e4%b8%80%e4%ba%9b%e6%93%8d%e4%bd%9c"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;mac上允许任何软件安装&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo spctl --master-disable
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;mac修改主机名&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo scutil --set HostName servername.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;设置简单密码&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pwpolicy -clearaccountpolicies
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;passwd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;重新设置所有的文件打开方式为默认&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -r local system -domain user
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="备份操作"&gt;
 备份操作
 &lt;a class="anchor" href="#%e5%a4%87%e4%bb%bd%e6%93%8d%e4%bd%9c"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;列出备份&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;➜ ~ tmutil listbackups
/Volumes/system/Backups.backupdb/MacBook Pro/2020-03-28-142200
/Volumes/system/Backups.backupdb/MacBook Pro/2020-04-04-125648
/Volumes/system/Backups.backupdb/MacBook Pro/2020-07-04-025359
/Volumes/system/Backups.backupdb/MacBook Pro/2020-07-04-031159
/Volumes/system/Backups.backupdb/MacBook Pro/2020-07-04-041113
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;删除备份&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;➜ ~ sudo tmutil delete /Volumes/system/Backups.backupdb/MacBook\ Pro/2020-03-28-142200
Password:
Deleting: /Volumes/system/Backups.backupdb/MacBook Pro/2020-03-28-142200
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="mac上截图方式"&gt;
 mac上截图方式
 &lt;a class="anchor" href="#mac%e4%b8%8a%e6%88%aa%e5%9b%be%e6%96%b9%e5%bc%8f"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;屏幕的一部分进行截图&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Command + shit + 4 截屏会保存在桌面
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;对整个屏幕进行截图&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Command + shift + 3 截屏会保存在桌面
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;把截图保存在粘贴板&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Command + Control + shift + 3 截取整个屏幕
Command + Control + shift + 4 选取部分截取
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;对打开的窗口进行截图&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Command + shfit + 4 + 空格键 保存在桌面可以再次按下空格键 进行调整大小，并可以使用 Command + Tab 进行窗口切换
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;Grap 实用程序工具&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="1macos系统重新安装设置"&gt;
 1、MacOS系统重新安装设置
 &lt;a class="anchor" href="#1macos%e7%b3%bb%e7%bb%9f%e9%87%8d%e6%96%b0%e5%ae%89%e8%a3%85%e8%ae%be%e7%bd%ae"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="u盘安装"&gt;
 U盘安装
 &lt;a class="anchor" href="#u%e7%9b%98%e5%ae%89%e8%a3%85"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;先格式化电脑硬盘&lt;/p&gt;</description></item><item><title>Rime 输入法</title><link>http://pemako.cn/blog/tools/rime/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/tools/rime/</guid><description>&lt;p&gt;&lt;a href="https://ssnhd.com/2022/01/06/rime/"&gt;https://ssnhd.com/2022/01/06/rime/&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id="rime-输入法使用指南"&gt;
 Rime 输入法使用指南
 &lt;a class="anchor" href="#rime-%e8%be%93%e5%85%a5%e6%b3%95%e4%bd%bf%e7%94%a8%e6%8c%87%e5%8d%97"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;h2 id="基本概念"&gt;
 基本概念
 &lt;a class="anchor" href="#%e5%9f%ba%e6%9c%ac%e6%a6%82%e5%bf%b5"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Rime 在 macOS 上叫 &lt;strong&gt;鼠须管（Squirrel）&lt;/strong&gt;，是一个高度可定制的输入法框架。所有配置通过 YAML 文件完成。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;配置目录：&lt;/strong&gt; &lt;code&gt;~/Library/Rime/&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一基本使用"&gt;
 一、基本使用
 &lt;a class="anchor" href="#%e4%b8%80%e5%9f%ba%e6%9c%ac%e4%bd%bf%e7%94%a8"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="切换输入方案"&gt;
 切换输入方案
 &lt;a class="anchor" href="#%e5%88%87%e6%8d%a2%e8%be%93%e5%85%a5%e6%96%b9%e6%a1%88"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;F4&lt;/code&gt; 或 &lt;code&gt;Ctrl+`&lt;/code&gt; — 呼出方案选单&lt;/li&gt;
&lt;li&gt;默认内置：朙月拼音、仓颉五代、粤拼等&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="切换中英文"&gt;
 切换中英文
 &lt;a class="anchor" href="#%e5%88%87%e6%8d%a2%e4%b8%ad%e8%8b%b1%e6%96%87"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Shift&lt;/code&gt; — 切换中英文（默认）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Caps Lock&lt;/code&gt; — 也可切换&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="翻页"&gt;
 翻页
 &lt;a class="anchor" href="#%e7%bf%bb%e9%a1%b5"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-&lt;/code&gt; / &lt;code&gt;=&lt;/code&gt; 或 &lt;code&gt;[&lt;/code&gt; / &lt;code&gt;]&lt;/code&gt; — 翻候选页&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="特殊输入"&gt;
 特殊输入
 &lt;a class="anchor" href="#%e7%89%b9%e6%ae%8a%e8%be%93%e5%85%a5"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/&lt;/code&gt; 开头 — 输入符号（如 &lt;code&gt;/jt&lt;/code&gt; → 箭头符号）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;v&lt;/code&gt; 开头 — 部分方案支持输入特殊字符&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="二配置文件结构"&gt;
 二、配置文件结构
 &lt;a class="anchor" href="#%e4%ba%8c%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6%e7%bb%93%e6%9e%84"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;~/Library/Rime/
├── squirrel.yaml # 外观配置（皮肤、字体）
├── default.yaml # 全局配置（方案列表、快捷键）
├── default.custom.yaml # ★ 你的全局自定义（推荐在这里改）
├── squirrel.custom.yaml # ★ 你的外观自定义
├── luna_pinyin.schema.yaml # 朙月拼音方案
├── luna_pinyin.custom.yaml # ★ 朙月拼音自定义
└── user.db / *.userdb/ # 用户词库
&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;关键原则：&lt;/strong&gt; 不要直接改 &lt;code&gt;*.yaml&lt;/code&gt;，要建对应的 &lt;code&gt;*.custom.yaml&lt;/code&gt; 文件来覆盖，这样升级不会丢失配置。&lt;/p&gt;</description></item><item><title>Tmux</title><link>http://pemako.cn/blog/tools/tmux/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/tools/tmux/</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/tmux/tmu#"&gt;https://github.com/tmux/tmu#&lt;/a&gt; tmux 使用&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="安装"&gt;
 安装
 &lt;a class="anchor" href="#%e5%ae%89%e8%a3%85"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;brew install tmux
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="配置"&gt;
 配置
 &lt;a class="anchor" href="#%e9%85%8d%e7%bd%ae"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;插件安装&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;全局配置&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# Enable mouse mode (tmux 2.1 and above)
set -g mouse on

#Enable oh my zsh in tmux
set -g default-command /bin/zsh

# Mouse based copy
bind-key -T copy-mode-vi MouseDragEnd1Pane send -X copy-pipe-and-cancel &amp;#34;reattach-to-user-namespace pbcopy&amp;#34;
bind-key -T copy-mode MouseDragEnd1Pane send -X copy-pipe-and-cancel &amp;#34;reattach-to-user-namespace pbcopy&amp;#34; 

set -g @continuum-boot &amp;#39;on&amp;#39; # Automatic Tmux start
set -g @continuum-restore &amp;#39;on&amp;#39; # Last saved environment is automatically restored when tmux is started
set -g @continuum-boot-options &amp;#39;iterm,fullscreen&amp;#39; # start iTerm in fullscreen

# tmux 的插件管理
set -g @plugin &amp;#39;tmux-plugin/tpm&amp;#39;
set -g @plugin &amp;#39;tmux-plugins/tmux-sensible&amp;#39;

set -g @plugin &amp;#39;tmux-plugins/tmux-resurrect&amp;#39;
set -g @plugin &amp;#39;tmux-plugins/tmux-continuum&amp;#39;

# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
run -b &amp;#39;~/.tmux/plugins/tpm/tpm&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;重载配置文件生效&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;tmux source ~/.tmux.conf
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="常用命令"&gt;
 常用命令
 &lt;a class="anchor" href="#%e5%b8%b8%e7%94%a8%e5%91%bd%e4%bb%a4"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# To start tmux:
tmux

# To detach from tmux:
Ctrl-b d

# To restore tmux session:
tmux attach

# To detach an already attached session (great if you are moving devices with different screen resolutions):
tmux attach -d 

# To display session:
tmux ls

# To rename session:
Ctrl-b $

# To switch session:
Ctrl-b s

# To start a shared session:
tmux -S /tmp/your_shared_session
chmod 777 /tmp/your_shared_session

# To help screen (Q to quit):
Ctrl-b ?

# To scroll in window:
Ctrl-b PageUp/PageDown

# To reload configuation file
Ctrl-b : source-file /path/to/file

# To create a window:
Ctrl-b c

# To go next window:
Ctrl-b n

# To destroy a window:
Ctrl-b x

# To switch between windows:
Ctrl-b [0-9]
Ctrl-b Arrows

# To split windows horizontally:
Ctrl-b %

# To split windows vertically:
Ctrl-b &amp;#34;

# To swap windows:
Ctrl-b :swap-window -s [0-9] -t [0-9]
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="问题总结"&gt;
 问题总结
 &lt;a class="anchor" href="#%e9%97%ae%e9%a2%98%e6%80%bb%e7%bb%93"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="iterm下滚动问题"&gt;
 iterm下滚动问题
 &lt;a class="anchor" href="#iterm%e4%b8%8b%e6%bb%9a%e5%8a%a8%e9%97%ae%e9%a2%98"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;进入iterm2 的设置 &lt;code&gt;Advanced&lt;/code&gt; 搜索 Scroll 找到 Mouse 下 &lt;code&gt;Scroll wheel sends arrow keys when in alternate screen mode.&lt;/code&gt; 修改为 &lt;code&gt;Yes&lt;/code&gt;。&lt;/p&gt;</description></item><item><title>Vim</title><link>http://pemako.cn/blog/tools/vim/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/tools/vim/</guid><description>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;行内单字符查找&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fx&lt;/code&gt; 向前查找本行中的字符 &lt;code&gt;x&lt;/code&gt; 其中 &lt;code&gt;f&lt;/code&gt;代表 &lt;code&gt;Find&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tx&lt;/code&gt; 移动的目标字符的前一个字符 &lt;code&gt;t&lt;/code&gt;代表&lt;code&gt;To&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;该命令的反向版本 &lt;code&gt;Tx&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;移动到指定的行&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;gg 行首&lt;/li&gt;
&lt;li&gt;G 行尾&lt;/li&gt;
&lt;li&gt;nG 指定行&lt;/li&gt;
&lt;li&gt;H(High)&lt;/li&gt;
&lt;li&gt;M(Middle)&lt;/li&gt;
&lt;li&gt;L（Low）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;滚屏&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CTRL-U 向下滚动半屏&lt;/li&gt;
&lt;li&gt;CTRL-D 把视窗向下移动半屏，也就是把文字向上移动半屏&lt;/li&gt;
&lt;li&gt;CTRL-E 向上滚一行&lt;/li&gt;
&lt;li&gt;CTRL-Y 向下滚一行&lt;/li&gt;
&lt;li&gt;CTRL-F (forwar) 向前滚动一屏&lt;/li&gt;
&lt;li&gt;CTRL-B (backward) 向后滚动一屏&lt;/li&gt;
&lt;li&gt;zt 把光标所在行移动到屏幕的顶部&lt;/li&gt;
&lt;li&gt;zb 移动到屏幕的底部&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;简单查找&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;字符 &lt;code&gt;.*[]^%/\?~$&lt;/code&gt; 有特殊含义。如果你要查找它们，需要在前面加上一个 &amp;ldquo;\&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;?&lt;/code&gt; 进行反向查找&lt;/li&gt;
&lt;li&gt;严格匹配一个单词&lt;code&gt;/the\&amp;gt;&lt;/code&gt; &lt;code&gt;\&amp;gt;&lt;/code&gt; 是一个特殊的记号，表示只匹配单词末尾。类似地，&lt;code&gt;\&amp;lt;&lt;/code&gt; 只匹配单词的开头&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;列块选择&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CTRL + V 启动可视模式&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;打开互联网上的文件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gf&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;放到对应链接上 &lt;code&gt;CRTL-W f&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;vim 变量 使用 &lt;code&gt;help internal-variables查看更多&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;b:name&lt;/code&gt; 缓冲区的局部变量&lt;/li&gt;
&lt;li&gt;&lt;code&gt;w:name&lt;/code&gt; 窗口的局部变量&lt;/li&gt;
&lt;li&gt;&lt;code&gt;g:name&lt;/code&gt; 全局变量（也用于函数中）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;v:name&lt;/code&gt; vim预定义的变量&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;vim的几种模式&lt;/p&gt;</description></item><item><title>小工具集合</title><link>http://pemako.cn/blog/tools/small-tools/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/tools/small-tools/</guid><description>&lt;h2 id="reference"&gt;
 Reference
 &lt;a class="anchor" href="#reference"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ffmpeg.org/documentation.html"&gt;https://ffmpeg.org/documentation.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="usage"&gt;
 Usage
 &lt;a class="anchor" href="#usage"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;flac to mp3&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ffmpeg -i input.flac -ab 320k -map_metadata 0 -id3v2_version 3 output.mp3&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ffplay
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.jianshu.com/p/c7c6871a8b7c"&gt;https://www.jianshu.com/p/c7c6871a8b7c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.jianshu.com/p/fd3c6d02a625"&gt;https://www.jianshu.com/p/fd3c6d02a625&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h1 id="vlc"&gt;
 VLC
 &lt;a class="anchor" href="#vlc"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;VLC 命令行播放音乐 参考 &lt;a href="https://wiki.videolan.org/Console/"&gt;https://wiki.videolan.org/Console/&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; ✗ vlc -I rc
VLC media player 3.0.16 Vetinari (revision 3.0.16-0-g5e70837d8d)
[00007fe29244ebe0] main playlist: playlist is empty
[00007fe292712650] [cli] lua interface: Listening on host &amp;#34;*console&amp;#34;.
VLC media player 3.0.16 Vetinari
Command Line Interface initialized. Type `help&amp;#39; for help.
&amp;gt; help
+----[ CLI commands ]
| add XYZ . . . . . . . . . . . . . . . . . . . . add XYZ to playlist
| enqueue XYZ . . . . . . . . . . . . . . . . . queue XYZ to playlist
| playlist . . . . . . . . . . . . . show items currently in playlist
| search [string] . . search for items in playlist (or reset search)
| delete [X] . . . . . . . . . . . . . . . . delete item X in playlist
| move [X][Y] . . . . . . . . . . . . move item X in playlist after Y
| sort key . . . . . . . . . . . . . . . . . . . . . sort the playlist
| sd [sd] . . . . . . . . . . . . . show services discovery or toggle
| play . . . . . . . . . . . . . . . . . . . . . . . . . . play stream
| stop . . . . . . . . . . . . . . . . . . . . . . . . . . stop stream
| next . . . . . . . . . . . . . . . . . . . . . . next playlist item
| prev . . . . . . . . . . . . . . . . . . . . previous playlist item
| goto, gotoitem . . . . . . . . . . . . . . . . . goto item at index
| repeat [on|off] . . . . . . . . . . . . . . toggle playlist repeat
| loop [on|off] . . . . . . . . . . . . . . . . toggle playlist loop
| random [on|off] . . . . . . . . . . . . . . toggle playlist random
| clear . . . . . . . . . . . . . . . . . . . . . clear the playlist
| status . . . . . . . . . . . . . . . . . . . current playlist status
| title [X] . . . . . . . . . . . . . . set/get title in current item
| title_n . . . . . . . . . . . . . . . . next title in current item
| title_p . . . . . . . . . . . . . . previous title in current item
| chapter [X] . . . . . . . . . . . . set/get chapter in current item
| chapter_n . . . . . . . . . . . . . . next chapter in current item
| chapter_p . . . . . . . . . . . . previous chapter in current item
|
| seek X . . . . . . . . . . . seek in seconds, for instance `seek 12&amp;#39;
| pause . . . . . . . . . . . . . . . . . . . . . . . . toggle pause
| fastforward . . . . . . . . . . . . . . . . . . set to maximum rate
| rewind . . . . . . . . . . . . . . . . . . . . . set to minimum rate
| faster . . . . . . . . . . . . . . . . . . faster playing of stream
| slower . . . . . . . . . . . . . . . . . . slower playing of stream
| normal . . . . . . . . . . . . . . . . . . normal playing of stream
| rate [playback rate] . . . . . . . . . . set playback rate to value
| frame . . . . . . . . . . . . . . . . . . . . . play frame by frame
| fullscreen, f, F [on|off] . . . . . . . . . . . . toggle fullscreen
| info [X] . . information about the current stream (or specified id)
| stats . . . . . . . . . . . . . . . . show statistical information
| get_time . . . . . . . . . seconds elapsed since stream&amp;#39;s beginning
| is_playing . . . . . . . . . . . . 1 if a stream plays, 0 otherwise
| get_title . . . . . . . . . . . . . the title of the current stream
| get_length . . . . . . . . . . . . the length of the current stream
|
| volume [X] . . . . . . . . . . . . . . . . . . set/get audio volume
| volup [X] . . . . . . . . . . . . . . . raise audio volume X steps
| voldown [X] . . . . . . . . . . . . . . lower audio volume X steps
| achan [X] . . . . . . . . . . . . set/get stereo audio output mode
| atrack [X] . . . . . . . . . . . . . . . . . . . set/get audio track
| vtrack [X] . . . . . . . . . . . . . . . . . . . set/get video track
| vratio [X] . . . . . . . . . . . . . . . set/get video aspect ratio
| vcrop, crop [X] . . . . . . . . . . . . . . . . set/get video crop
| vzoom, zoom [X] . . . . . . . . . . . . . . . . set/get video zoom
| vdeinterlace [X] . . . . . . . . . . . . . set/get video deinterlace
| vdeinterlace_mode [X] . . . . . . . set/get video deinterlace mode
| snapshot . . . . . . . . . . . . . . . . . . . . take video snapshot
| strack [X] . . . . . . . . . . . . . . . . . set/get subtitle track
|
| vlm . . . . . . . . . . . . . . . . . . . . . . . . . load the VLM
| description . . . . . . . . . . . . . . . . . describe this module
| help, ? [pattern] . . . . . . . . . . . . . . . . . a help message
| longhelp [pattern] . . . . . . . . . . . . . . a longer help message
| lock . . . . . . . . . . . . . . . . . . . . lock the telnet prompt
| logout . . . . . . . . . . . . . . exit (if in a socket connection)
| quit . . . . . . . . quit VLC (or logout if in a socket connection)
| shutdown . . . . . . . . . . . . . . . . . . . . . . . shutdown VLC
+----[ end of help ]
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;p&gt;&lt;a href="https://github.com/pemako/beancount"&gt;https://github.com/pemako/beancount&lt;/a&gt;&lt;/p&gt;</description></item><item><title>终端原理</title><link>http://pemako.cn/blog/tools/terminal/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/tools/terminal/</guid><description>&lt;h1 id="go-终端编程原理详解"&gt;
 Go 终端编程原理详解
 &lt;a class="anchor" href="#go-%e7%bb%88%e7%ab%af%e7%bc%96%e7%a8%8b%e5%8e%9f%e7%90%86%e8%af%a6%e8%a7%a3"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;基于 &lt;code&gt;golang.org/x/term&lt;/code&gt; 和 &lt;code&gt;github.com/creack/pty&lt;/code&gt; 的完整技术文档&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="目录"&gt;
 目录
 &lt;a class="anchor" href="#%e7%9b%ae%e5%bd%95"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#1-%e7%bb%88%e7%ab%af%e5%9f%ba%e7%a1%80%e6%a6%82%e5%bf%b5"&gt;终端基础概念&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#2-%e6%96%87%e4%bb%b6%e6%8f%8f%e8%bf%b0%e7%ac%a6"&gt;文件描述符&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#3-termios%e7%bb%88%e7%ab%af-io-%e6%8e%a7%e5%88%b6"&gt;termios：终端 I/O 控制&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#4-cooked-%e6%a8%a1%e5%bc%8f-vs-raw-%e6%a8%a1%e5%bc%8f"&gt;Cooked 模式 vs Raw 模式&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#5-golangorgxterm-api-%e8%af%a6%e8%a7%a3"&gt;golang.org/x/term API 详解&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#6-pty%e4%bc%aa%e7%bb%88%e7%ab%af%e5%8e%9f%e7%90%86"&gt;PTY（伪终端）原理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#7-%e5%ae%8c%e6%95%b4%e7%a4%ba%e4%be%8b%e8%a7%a3%e6%9e%90"&gt;完整示例解析&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#8-%e5%b8%b8%e8%a7%81%e9%97%ae%e9%a2%98%e4%b8%8e%e6%9c%80%e4%bd%b3%e5%ae%9e%e8%b7%b5"&gt;常见问题与最佳实践&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#9-%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99"&gt;参考资料&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="1-终端基础概念"&gt;
 1. 终端基础概念
 &lt;a class="anchor" href="#1-%e7%bb%88%e7%ab%af%e5%9f%ba%e7%a1%80%e6%a6%82%e5%bf%b5"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="什么是终端terminal"&gt;
 什么是终端（Terminal）
 &lt;a class="anchor" href="#%e4%bb%80%e4%b9%88%e6%98%af%e7%bb%88%e7%ab%afterminal"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;终端最初是物理设备（电传打字机、CRT 显示器），通过串口连接到主机，用于输入命令和查看输出。现代操作系统中的&amp;quot;终端&amp;quot;是对这一概念的软件模拟，称为&lt;strong&gt;终端模拟器&lt;/strong&gt;（Terminal Emulator），如 macOS 的 Terminal.app、iTerm2，Linux 上的 GNOME Terminal 等。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;用户键盘输入
 │
 ▼
┌─────────────┐ ┌──────────────┐ ┌─────────┐
│ 终端模拟器 │─────▶│ TTY 驱动层 │─────▶│ 进程 │
│ (Terminal) │◀─────│ (内核) │◀─────│ (Shell) │
└─────────────┘ └──────────────┘ └─────────┘
 │
 ▼
屏幕显示输出
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="tty-与终端设备文件"&gt;
 TTY 与终端设备文件
 &lt;a class="anchor" href="#tty-%e4%b8%8e%e7%bb%88%e7%ab%af%e8%ae%be%e5%a4%87%e6%96%87%e4%bb%b6"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;在 Linux/macOS 中，终端通过特殊的设备文件暴露给进程：&lt;/p&gt;</description></item><item><title>虚拟机安装</title><link>http://pemako.cn/blog/tools/vm-setup/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/tools/vm-setup/</guid><description>&lt;h2 id="系统下载安装"&gt;
 系统下载安装
 &lt;a class="anchor" href="#%e7%b3%bb%e7%bb%9f%e4%b8%8b%e8%bd%bd%e5%ae%89%e8%a3%85"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;说明该版本的系统主要是作为学习 《程序员的自我修养》这本书的环境&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;下载对应的 iso 镜像版本 &lt;a href="https://old-releases.ubuntu.com/releases/7.04/"&gt;https://old-releases.ubuntu.com/releases/7.04/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;配置 ubuntu 提供的老的 apt 镜像源 &lt;a href="https://askubuntu.com/questions/91815/how-to-install-software-or-upgrade-from-an-old-unsupported-release?rq=1"&gt;问题1&lt;/a&gt; &lt;a href="https://askubuntu.com/questions/386265/media-change-please-insert-the-disc-labeled-when-trying-to-install-ruby-on-ra"&gt;问题2&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 先备份&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cp /etc/apt/sources.list /etc/apt/sources.list.bak
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 替换&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo sed -i -re &lt;span style="color:#e6db74"&gt;&amp;#39;s/([a-z]{2}\.)?archive.ubuntu.com|security.ubuntu.com/old-releases.ubuntu.com/g&amp;#39;&lt;/span&gt; /etc/apt/sources.list
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# then update with&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt-get update &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt-get dist-upgrade
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 删除 cdrom 的行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#e6db74"&gt;&amp;#39;/cdrom/d&amp;#39;&lt;/span&gt; /etc/apt/sources.list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="网络配置"&gt;
 网络配置
 &lt;a class="anchor" href="#%e7%bd%91%e7%bb%9c%e9%85%8d%e7%bd%ae"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;这里主要是想固定虚拟机的ip地址，开启 ssh 服务，这样可以通过终端登录。故这里选择的网络模式为 Nat + Host-only 模式。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在 &lt;code&gt;Tools-&amp;gt;Network-&amp;gt;Create&lt;/code&gt; 选择 &lt;code&gt;Host-only Networks&lt;/code&gt; 添加一个网络配置&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://raw.githubusercontent.com/pemako/assets/main/2024/05/202404301007760.png" alt="image-20240430100754595" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在虚拟机的 &lt;code&gt;Settings-&amp;gt;Network-&amp;gt;Adapter 1&lt;/code&gt; 中选择 &lt;code&gt;NAT&lt;/code&gt; （这里默认选择）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://raw.githubusercontent.com/pemako/assets/main/2024/05/202404301010933.png" alt="image-20240430101045905" /&gt;&lt;/p&gt;</description></item></channel></rss>