<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Hello World</title>
    <link>https://qiqijin.com/blog/</link>
    <atom:link href="https://qiqijin.com/blog/feed.xml" rel="self" type="application/rss+xml" />
    <description>This is a blog for Qiqi Jin.</description>
    <language>zh-CN</language>
    <item>
      <title>Org Reminders</title>
      <link>https://qiqijin.com/blog/posts/20250601-org-reminders/</link>
      <description>&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;
&lt;p&gt;I use Reminders on my iPhone or iPad for daily to-dos, but Emacs org
mode on my computer. This makes switching between the two applications
uncomfortable.&lt;/p&gt;
&lt;p&gt;Org mode is a powerful tool for editing and managing to-do lists on a
computer. Apps like &lt;a href=&quot;https://www.beorgapp.com/&quot;&gt;beorg&lt;/a&gt; allow
you to edit and sync Org mode files on mobile devices. You can use it to
get a familiar experience on computers and mobile devices.&lt;/p&gt;
&lt;p&gt;But I think Reminders offers a simpler, more intuitive mobile
experience. I&#39;m building an Emacs plugin to sync to-dos between Org mode
and Reminders.&lt;/p&gt;
&lt;p&gt;Thanks &lt;a href=&quot;https://github.com/keith/reminders-cli&quot;&gt;reminders-cli&lt;/a&gt; to
provide a simple and good performance CLI tool for interacting with
macOS reminders.&lt;/p&gt;
&lt;p&gt;Because I needed specific features, I forked it to &lt;a href=&quot;https://github.com/ginqi7/reminders-cli/&quot;&gt;ginqi7@reminders-cli&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Thanks &lt;a href=&quot;https://github.com/jdtsmith&quot;&gt;jdtsmith&lt;/a&gt; provide
great ideas for true sync logic. this is the &lt;a href=&quot;https://github.com/ginqi7/org-reminders/issues/2&quot;&gt;discuss&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;design&quot;&gt;Design&lt;/h2&gt;
&lt;h3 id=&quot;project-structure&quot;&gt;Project Structure&lt;/h3&gt;
&lt;p&gt;There are two components:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;org-reminders-cli&lt;/strong&gt; : A controller for monitoring the
org mode file and Reminders. When changes occur in the org mode file or
Reminders, it compares the differences between them, updates Reminders,
or sends messages to Emacs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;org-reminders elisp&lt;/strong&gt; : A frontend that receives
messages from org-reminders-cli and updates the org mode file.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://qiqijin.com/blog/images/org-reminders.svg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;websocket-bridge&quot;&gt;Websocket-bridge&lt;/h3&gt;
&lt;p&gt;Using WebSocket bridge to communicate between Emacs and a Swift
program enhances message handling robustness.&lt;/p&gt;
&lt;h3 id=&quot;treesite-org&quot;&gt;Treesite-org&lt;/h3&gt;
&lt;p&gt;Parsing the org mode file using org-tree-sitter is remarkably
efficient, processing ten thousand items in under one second.&lt;/p&gt;
</description>
      <pubDate>Sun, 01 Jun 2025 00:00:00 GMT</pubDate>
      <dc:creator>Qiqi Jin</dc:creator>
      <guid>https://qiqijin.com/blog/posts/20250601-org-reminders/</guid>
    </item>
    <item>
      <title>Emacs Brew Manager</title>
      <link>https://qiqijin.com/blog/posts/20250409-emacs-brew-man/</link>
      <description>&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;A simple Homebrew manager by Emacs.&lt;/p&gt;
&lt;p&gt;The brew CLI is already sufficient for adding, deleting, or searching
for formulae. However, when reviewing installed formulae — such as
identifying unused ones or checking for version updates — a GUI is more
convenient. That&#39;s why I created this Emacs package to manage installed
formulae with additional features.&lt;/p&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;/h2&gt;
&lt;h3 id=&quot;display-all-installed-formulae-and-casks.&quot;&gt;Display all installed
Formulae and Casks.&lt;/h3&gt;
&lt;p&gt;You can view all installed Formulae and Casks, with columns
indicating the available new versions for updates and whether the
Formula or Cask is used by other Formulae or Casks.&lt;/p&gt;
&lt;p&gt;You can use the list information to decide which formulae and casks
to delete or update, making your computer system cleaner and more
controllable.&lt;/p&gt;
&lt;h3 id=&quot;display-all-installed-taps.&quot;&gt;Display all installed Taps.&lt;/h3&gt;
&lt;p&gt;You can check the Tap to see how many Formulae and Casks are
available and how many are installed.&lt;/p&gt;
&lt;p&gt;You can delete unnecessary taps and interactively select to install
Formulae or Casks provided by a specific tap.&lt;/p&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;Essentially, it is a wrapper around the brew command line, utilizing
&lt;a href=&quot;https://github.com/ginqi7/websocket-bridge-ruby&quot;&gt;websocket-bridge-ruby&lt;/a&gt;
as a bridge. The choice of Ruby is due to its ease in handling shell
outcomes.&lt;/p&gt;
</description>
      <pubDate>Wed, 09 Apr 2025 00:00:00 GMT</pubDate>
      <dc:creator>Qiqi Jin</dc:creator>
      <guid>https://qiqijin.com/blog/posts/20250409-emacs-brew-man/</guid>
    </item>
    <item>
      <title>Image Slicing</title>
      <link>https://qiqijin.com/blog/posts/20240601-image-slicing/</link>
      <description>&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;
&lt;p&gt;In Emacs, displaying an image occupies one line regardless of its
height. The movement over the image while navigating by lines can be
quite frustrating.&lt;/p&gt;
&lt;p&gt;Although &lt;a href=&quot;https://github.com/emacs-mirror/emacs/blob/master/lisp/pixel-scroll.el&quot;&gt;pixel-scroll&lt;/a&gt;
and &lt;a href=&quot;https://github.com/emacs-mirror/emacs/blob/master/lisp/pixel-scroll.el&quot;&gt;iscroll&lt;/a&gt;
have improved image movement to some extent.&lt;/p&gt;
&lt;p&gt;I hope to move images in the same way as moving text, line by
line.&lt;/p&gt;
&lt;p&gt;So I created this package to horizontally slice the images referenced
in the buffer into multiple images. In Emacs, only a portion of the
original image is displayed on each line. Finally, the image can be
moved line by line.&lt;/p&gt;
&lt;p&gt;During the development process, I found &lt;a href=&quot;https://github.com/jcfk/org-sliced-images&quot;&gt;org-sliced-images&lt;/a&gt;
which was almost the same as my idea. And thanks to him for letting me
know about &lt;code class=&quot;verbatim&quot;&gt;insert-sliced-image&lt;/code&gt; in
Emacs.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;
&lt;h3 id=&quot;cli&quot;&gt;CLI&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Curl&lt;/strong&gt;: Used to download remote images.&lt;/p&gt;
&lt;h3 id=&quot;require-packages&quot;&gt;Require Packages&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;org-element&lt;/strong&gt;: Used to parse the buffer to retrieve
all links.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;image&lt;/strong&gt;: Used to create an image object.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;url-util&lt;/strong&gt; : A utility for handling URL formats.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;install&quot;&gt;Install&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;clone the project in your own emacs configuration files directory,
like:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot; data-org-language=&quot;sh&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;https://qiqijin.com/blog/#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;fu&quot;&gt;git&lt;/span&gt; clone git@github.com:ginqi7/image-slicing.git ~/.emacs.d/lisp/image-slicing&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;add the path to &#39;load-path&#39;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot; data-org-language=&quot;emacs-lisp&quot;&gt;&lt;pre class=&quot;sourceCode commonlisp&quot;&gt;&lt;code class=&quot;sourceCode commonlisp&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;https://qiqijin.com/blog/#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;(add-to-list &lt;span class=&quot;dt&quot;&gt;&amp;#39;load-path&lt;/span&gt; (expand-file-name &lt;span class=&quot;st&quot;&gt;&amp;quot;~/.emacs.d/lisp/d/lisp/image-slicing&amp;quot;&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;configuration&quot;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;Here are a few variables that can be used for configuration:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot; data-org-language=&quot;emacs-lisp&quot;&gt;&lt;pre class=&quot;sourceCode commonlisp&quot;&gt;&lt;code class=&quot;sourceCode commonlisp&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;https://qiqijin.com/blog/#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;(&lt;span class=&quot;kw&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;&amp;#39;image-slicing&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;variables&quot;&gt;Variables&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;variable&lt;/th&gt;
&lt;th&gt;default value&lt;/th&gt;
&lt;th&gt;explain&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;image-slicing-download-concurrency&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;the maximum concurrency of images download&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;image-slicing-line-height-scale&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;how many line height an image slice occupies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;image-slicing-max-width&lt;/td&gt;
&lt;td&gt;700&lt;/td&gt;
&lt;td&gt;the maximum width of images display&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;image-slicing-cursor-fringe-bitmaps&lt;/td&gt;
&lt;td&gt;&#39;(left-fringe right-arrow warning)&lt;/td&gt;
&lt;td&gt;the Fringe Bitmaps indicator for the cursor position.&lt;a href=&quot;https://qiqijin.com/blog/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;eww-config&quot;&gt;EWW Config&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;cancel the eww defualt image render.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot; data-org-language=&quot;emacs-lisp&quot;&gt;&lt;pre class=&quot;sourceCode commonlisp&quot;&gt;&lt;code class=&quot;sourceCode commonlisp&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;https://qiqijin.com/blog/#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;(add-to-list &lt;span class=&quot;dt&quot;&gt;&amp;#39;shr-external-rendering-functions&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;https://qiqijin.com/blog/#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;             &amp;#39;(img . image-slicing-tag-img))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;image-slicing&lt;/code&gt; to
&lt;code&gt;eww-after-render-hook&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot; data-org-language=&quot;emacs-lisp&quot;&gt;&lt;pre class=&quot;sourceCode commonlisp&quot;&gt;&lt;code class=&quot;sourceCode commonlisp&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;https://qiqijin.com/blog/#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;(&lt;span class=&quot;kw&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;#&amp;#39;&lt;/span&gt;image-slicing-mode eww-after-render-hook)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;elfeed-config&quot;&gt;Elfeed Config&lt;/h3&gt;
&lt;p&gt;image-slice can also work with elfeed:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot; data-org-language=&quot;emacs-lisp&quot;&gt;&lt;pre class=&quot;sourceCode commonlisp&quot;&gt;&lt;code class=&quot;sourceCode commonlisp&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;https://qiqijin.com/blog/#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;;; add to shr-external-rendering-functions (skip if alread setup for eww)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;https://qiqijin.com/blog/#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;(add-to-list &lt;span class=&quot;dt&quot;&gt;&amp;#39;shr-external-rendering-functions&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;https://qiqijin.com/blog/#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;             &amp;#39;(img . image-slicing-tag-img))&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;https://qiqijin.com/blog/#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;https://qiqijin.com/blog/#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;;; advice `elfeed-show-entry&amp;#39; to trigger `image-slicing-mode&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-6&quot;&gt;&lt;a href=&quot;https://qiqijin.com/blog/#cb6-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;(advice-add &lt;span class=&quot;op&quot;&gt;#&amp;#39;&lt;/span&gt;elfeed-show-entry :after &lt;span class=&quot;op&quot;&gt;#&amp;#39;&lt;/span&gt;image-slicing-mode)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;verbatim&quot;&gt;image-slicing-mode&lt;/code&gt;: Automatically
finds image links in the buffer and renders them as multiline
display.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;verbatim&quot;&gt;Asynchronous&lt;/code&gt;: Asynchronous download of
remote images.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;verbatim&quot;&gt;Multiple Modes&lt;/code&gt;: Support multiple modes
like org-mode, eww, elfeed.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;supported-link-format&quot;&gt;Supported Link Format&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Org Links
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;verbatim&quot;&gt;[[url][tag]]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;verbatim&quot;&gt;[[url]]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Pure Links
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;verbatim&quot;&gt;file:./hello.png&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;verbatim&quot;&gt;http://image.png&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;EWW Html Links
&lt;ul&gt;
&lt;li&gt;&amp;lt;img src=&#39;&#39;&amp;gt;&lt;/li&gt;
&lt;li&gt;Support base64 formatted images&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;example&quot;&gt;Example&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/ginqi7/image-slicing/raw/main/screencast.gif&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;disadvantages&quot;&gt;Disadvantages&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;If there are many remote image links in the buffer, it will generate
many temporary image files in the temporary system directory.&lt;/li&gt;
&lt;li&gt;If the URL link is too short, the number of slices of the original
image will be small, and the image line height will be large.&lt;/li&gt;
&lt;li&gt;Only one buffer can be rendered at a time.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;todo-list&quot;&gt;Todo List&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Adapt nov&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;development-history&quot;&gt;Development History&lt;/h2&gt;
&lt;h3 id=&quot;dec-18-2024&quot;&gt;Dec 18, 2024&lt;/h3&gt;
&lt;p&gt;I find a similar package named &lt;a href=&quot;https://github.com/jcfk/org-sliced-images&quot;&gt;org-sliced-images&lt;/a&gt;,
so I study some code from it to make my code simpler.&lt;/p&gt;
&lt;p&gt;In Emacs, we can display a part of an image by using (&#39;display .
(list (list &#39;slice x y dx dy) image)), without needing to actually slice
the image using ImageMagick, so I remove the dependency about
ImageMagick.&lt;/p&gt;
&lt;h3 id=&quot;dec-16-2024&quot;&gt;Dec 16, 2024&lt;/h3&gt;
&lt;p&gt;There have some issues in last version:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;There is slow when ImageMagick handle remote images.&lt;/li&gt;
&lt;li&gt;Though I will delete the placeholders when the user removes the
overlays, there is still a risk of polluting the users&#39; buffer.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So I use asynchronous processes to run ImageMagick, guaranteeing that
it will not freeze Emacs. On the other hand, I removed the placeholder
and just placed some overlays on the original URL text.&lt;/p&gt;
&lt;h3 id=&quot;may-12-2023&quot;&gt;May 12, 2023&lt;/h3&gt;
&lt;p&gt;I got the idea to slice the image into many pieces, making Emacs
display the pieces line by line.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use the CLI &lt;em&gt;&lt;a href=&quot;https://imagemagick.org/&quot;&gt;ImageMagick&lt;/a&gt;&lt;/em&gt; to slice
images.&lt;/li&gt;
&lt;li&gt;Insert some special text like &quot;&lt;u&gt;&lt;u&gt;#_#_@@_#_#&lt;/u&gt;&lt;/u&gt;&quot; as
placeholder, and put an overlay on that placeholder to show image
pieces.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/Fringe-Bitmaps.html&quot;&gt;Emacs
Fringe Bitmaps&lt;/a&gt;&lt;a href=&quot;https://qiqijin.com/blog/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
      <pubDate>Sat, 01 Jun 2024 00:00:00 GMT</pubDate>
      <dc:creator>Qiqi Jin</dc:creator>
      <guid>https://qiqijin.com/blog/posts/20240601-image-slicing/</guid>
    </item>
    <item>
      <title>&quot;Project Hail Mary&quot; Reading Notes</title>
      <link>https://qiqijin.com/blog/posts/20230601-project_hail_mary_reading_notes/</link>
      <description>&lt;blockquote&gt;
&lt;p&gt;Author: Andy Weir&lt;/p&gt;
&lt;p&gt;Other works: The Martian&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The second novel by Andy Weir that I&#39;ve read. His science fiction is
still relatively easy to understand, without any particularly profound
concepts. The story creates a crisis environment and uses basic physics
concepts to solve problems step by step.&lt;/p&gt;
&lt;p&gt;The protagonist is not a hero who sacrifices everything to save the
world, and is even timid. However, he remains a person of integrity,
always acting for the benefit of the world when faced with difficult
decisions.&lt;/p&gt;
&lt;p&gt;In the end, he proves more decisive in saving his friends than in
saving the world itself.&lt;/p&gt;
&lt;p&gt;The final ending is quite interesting, avoiding depictions of a
devastated Earth or a hero&#39;s return. Instead, it opens up a whole new
world.&lt;/p&gt;
&lt;p&gt;And until the very end, the protagonist remains just an ordinary
teacher.&lt;/p&gt;
</description>
      <pubDate>Thu, 01 Jun 2023 00:00:00 GMT</pubDate>
      <dc:creator>Qiqi Jin</dc:creator>
      <guid>https://qiqijin.com/blog/posts/20230601-project_hail_mary_reading_notes/</guid>
    </item>
    <item>
      <title>Using Emacs Combine Anything</title>
      <link>https://qiqijin.com/blog/posts/20220601-using_emacs_combine_anything/</link>
      <description>&lt;p&gt;I&#39;ve written several Emacs tools to be more productive. As an Emacs
Lisp novice, instead of writing pure Emacs Lisp programs, I used Emacs
Lisp to encapsulate several console tools and use Emacs as an adhesive.
Overall, it feels good to use.&lt;/p&gt;
&lt;p&gt;I feel using Emacs as a console tools&#39; GUI interface is a good
choice. On the one hand, it can reuse a series of methods and plugins of
Emacs and write some frequent operations as Emacs functions and bind
them to a shortcut key. You can run some console commands easily and
quickly while writing documents, On the other hand, there is no need to
repeat the core logic of console tools.&lt;/p&gt;
&lt;p&gt;Recently wrote for 4 Emacs tools:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;leetcode-emacs: &lt;a href=&quot;https://github.com/ginqi7/leetcode-emacs&quot;&gt;https://github.com/ginqi7/leetcode-emacs&lt;/a&gt;,
an emacs plugin to write Leetcode programs&lt;/li&gt;
&lt;li&gt;hbase-shell-emacs: &lt;a href=&quot;https://github.com/ginqi7/hbase-shell-emacs&quot;&gt;https://github.com/ginqi7/hbase-shell-emacs&lt;/a&gt;,
A Emacs Plugin for Hbase shell&lt;/li&gt;
&lt;li&gt;kubectl-emacs: &lt;a href=&quot;https://github.com/ginqi7/kubectl-emacs&quot;&gt;https://github.com/ginqi7/kubectl-emacs&lt;/a&gt;,
This is an Emacs plugin that makes it easier and faster to manage k8s
using kubectl.&lt;/li&gt;
&lt;li&gt;global-interactive-emacs: &lt;a href=&quot;https://github.com/ginqi7/global-interactive-emacs&quot;&gt;https://github.com/ginqi7/global-interactive-emacs&lt;/a&gt;,
Global Interactive Emacs&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These tools can be divided into two categories:&lt;/p&gt;
&lt;p&gt;The first 3 tools use Emacs as a GUI or interactive interface for a
series of command-line tools&lt;/p&gt;
&lt;p&gt;The last one is using Emacs as the backend of the system application
shortcut launcher. Use interactive methods outside of Emacs defined in
Emacs.&lt;/p&gt;
&lt;h2 id=&quot;using-emacs-as-a-gui-or-interactive-interface&quot;&gt;Using Emacs as a
GUI or interactive interface&lt;/h2&gt;
&lt;p&gt;The idea and implementation of using Emacs as a GUI or interactive
interface are very simple and intuitive.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using emacs to define an interactive function for command-line
tools, while you want to fuzz search some options or inputs to run a
complex command.&lt;/li&gt;
&lt;li&gt;Using emacs &lt;code class=&quot;verbatim&quot;&gt;ctable&lt;/code&gt;&lt;a href=&quot;https://qiqijin.com/blog/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; to
list outputs and bind some function on hotkey in its cell, while you
want to review command-line tools&#39; output, and run some frequency
operations on some specific output.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;example&quot;&gt;Example&lt;/h3&gt;
&lt;p align=&quot;center&quot;&gt;&lt;img width=&quot;600px&quot; src=&quot;https://github.com/ginqi7/leetcode-emacs/raw/master/resources/leetcode-filter-by-tag.gif&quot;&gt;&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;img width=&quot;600px&quot; src=&quot;https://github.com/ginqi7/kubectl-emacs/raw/main/images/kubect-get-interactive.gif&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;global-interactive-emacs&quot;&gt;Global Interactive Emacs&lt;/h2&gt;
&lt;p&gt;This tool is inspired by article : &lt;a href=&quot;https://isamert.net/2022/03/16/global-interactive-emacs-functions.html&quot;&gt;Global
interactive Emacs functions&lt;/a&gt;.It provides an idea to run Emacs
functions outside of Emacs.&lt;/p&gt;
&lt;p&gt;So I try to use this idea to write a tool like &lt;a href=&quot;https://www.obdev.at/products/launchbar/index.html&quot;&gt;lauchbar&lt;/a&gt;
or &lt;a href=&quot;https://www.alfredapp.com/&quot;&gt;Alfred&lt;/a&gt;. It can help users
quickly launch apps or run workflows.&lt;/p&gt;
&lt;p&gt;I&#39;m using it to replace the Launchbar.&lt;/p&gt;
&lt;h3 id=&quot;principle&quot;&gt;Principle&lt;/h3&gt;
&lt;p&gt;the idea of &lt;code class=&quot;verbatim&quot;&gt;Global Interactive Emacs&lt;/code&gt; is
so interesting.&lt;/p&gt;
&lt;p&gt;On Emacs, using &lt;code class=&quot;verbatim&quot;&gt;completing-function&lt;/code&gt; to
implement interactive function, it will use minibuffer to input function
parameter.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;verbatim&quot;&gt;Global Interactive Emacs&lt;/code&gt; overwrite the
&lt;code class=&quot;verbatim&quot;&gt;completing-function&lt;/code&gt;, using &lt;code class=&quot;verbatim&quot;&gt;choose&lt;/code&gt;&lt;a href=&quot;https://qiqijin.com/blog/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; to accept parameter. So
we can run Emacs interactive function without focus Emacs.&lt;/p&gt;
&lt;h3 id=&quot;pros-and-cons&quot;&gt;Pros and cons&lt;/h3&gt;
&lt;p&gt;This tool has some pros and cons, and I think if you have the
following needs, you can try to use it :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you don&#39;t want pay for other tools like &lt;a href=&quot;https://www.obdev.at/products/launchbar/index.html&quot;&gt;lauchbar&lt;/a&gt;
or &lt;a href=&quot;https://www.alfredapp.com/&quot;&gt;Alfred&lt;/a&gt; .&lt;/li&gt;
&lt;li&gt;you wish some function in Emacs could run out of Emacs.&lt;/li&gt;
&lt;li&gt;You&#39;re familiar with Emacs, there are some plugins, and custom
functions that you want to reuse.&lt;/li&gt;
&lt;li&gt;You don&#39;t want to learn a new language or workflow of a new
software&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;pros&quot;&gt;Pros&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;free&lt;/strong&gt;: Whether Lauchbar or Alfred, you need to pay
for it to use it comfortably and efficiently. Just need &lt;code class=&quot;verbatim&quot;&gt;Emacs&lt;/code&gt; and some open source software that you can
use for free.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;consistency&lt;/strong&gt;: You can use the same features inside
or outside of Emacs and have a similar experience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simple Configuration&lt;/strong&gt;: If you are familiar with
Emacs, you can easily configure it with emacs-lisp without having to
relearn the language and process of other tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: You can write your interactive
functions and plug them into the tool, or use the Emacs plugins
developed by others to extract the interaction functions and plug them
into the tool.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;cons&quot;&gt;Cons&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Not powerful for now&lt;/strong&gt;: Obviously, the tool is not as
powerful as Lauchbar or Alfred. At the moment it is only useful for my
own needs. I will continue to improve according to my needs, and anyone
is welcome to help improve it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Can&#39;t perfectly support all Emacs interactive
functions&lt;/strong&gt;: There are currently some Emacs interaction functions
that cannot be run outside of Emacs, such as &lt;code class=&quot;verbatim&quot;&gt;execute-extended-command&lt;/code&gt;. I don&#39;t have the train
of thought to support it yet.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;example-1&quot;&gt;Example&lt;/h3&gt;
&lt;p align=&quot;center&quot;&gt;&lt;img width=&quot;600px&quot; src=&quot;https://github.com/ginqi7/global-interactive-emacs/raw/main/example/global-interactive-open-url.gif&quot;&gt;&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;img width=&quot;600px&quot; src=&quot;https://github.com/ginqi7/global-interactive-emacs/raw/main/example/global-interactive-run-app.gif&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/kiwanami/emacs-ctable&quot;&gt;emacs-ctable&lt;/a&gt; : Table
Component for elisp&lt;a href=&quot;https://qiqijin.com/blog/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/chipsenkbeil/choose&quot;&gt;choose
github&lt;/a&gt; :Fuzzy matcher for OS X that uses both std{in,out} and a
native GUI&lt;a href=&quot;https://qiqijin.com/blog/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
      <pubDate>Wed, 01 Jun 2022 00:00:00 GMT</pubDate>
      <dc:creator>Qiqi Jin</dc:creator>
      <guid>https://qiqijin.com/blog/posts/20220601-using_emacs_combine_anything/</guid>
    </item>
    <item>
      <title>Goodbye, Time</title>
      <link>https://qiqijin.com/blog/posts/20130601-goodbye,_time/</link>
      <description>&lt;p&gt;When we first parted, we each entered different worlds, some fresh
and exciting, others daunting and frightening. We often talked about our
experiences, sometimes with excitement, sometimes with sadness. We felt
that at this moment, we had someone to confide in, to share our joys and
sorrows with. It felt warm and beautiful, and our relationship felt
deeper than ever before.&lt;/p&gt;
&lt;p&gt;As time went on, we got used to our new worlds and became busy with
our own lives. We still kept in touch with each other, but we soon
realized that sometimes we couldn&#39;t help each other with our problems or
understand each other&#39;s joy.&lt;/p&gt;
&lt;p&gt;When we finally reunited after a long time, we had so much to say,
but didn&#39;t know where to start, so we just chatted about the weather and
other small things. Before we knew it, we had run out of things to say.
Maybe we weren&#39;t old enough to reminisce endlessly about the past, or
maybe we had completely different perspectives on new things. We didn&#39;t
burst each other&#39;s bubbles, we just continued with small talk.
Occasionally, we shared our thoughts, but found it difficult to agree
with each other, so we either nodded and said &quot;I agree,&quot; or just smiled
and changed the subject. If someone else were to observe our
conversation, they would see two people laughing and agreeing with each
other, seemingly in harmony.&lt;/p&gt;
&lt;p&gt;As we parted ways again, &quot;we exchanged pleasantries and promises to
meet again&quot;, and each breathed a sigh of relief as the other left.&lt;/p&gt;
&lt;p&gt;On the way home, thinking back to our meeting, tears welled up in our
eyes.&lt;/p&gt;
</description>
      <pubDate>Sat, 01 Jun 2013 00:00:00 GMT</pubDate>
      <dc:creator>Qiqi Jin</dc:creator>
      <guid>https://qiqijin.com/blog/posts/20130601-goodbye,_time/</guid>
    </item>
    <item>
      <title>Chess Game</title>
      <link>https://qiqijin.com/blog/posts/20120601-chess_game/</link>
      <description>&lt;p&gt;It&#39;s like when you invite someone to play chess with you. You are
full of enthusiasm and think that the other person is also enjoying it.
Until the end, when he pushes the chessboard away and leaves, you
realize that he was bored and couldn&#39;t bear it anymore. Looking back at
the chess game, you can see his emotions everywhere, but you didn&#39;t
notice it at all. The reason is that you thought you had similar
interests, while he thought he could tolerate it. In the end, when the
chess game is over, one person is full of complaints, while the other is
confused. If you had communicated your thoughts from the beginning, the
outcome might have been different.&lt;/p&gt;
</description>
      <pubDate>Fri, 01 Jun 2012 00:00:00 GMT</pubDate>
      <dc:creator>Qiqi Jin</dc:creator>
      <guid>https://qiqijin.com/blog/posts/20120601-chess_game/</guid>
    </item>
    <item>
      <title>The Story Ending</title>
      <link>https://qiqijin.com/blog/posts/20110601-the_story_ending/</link>
      <description>&lt;p&gt;On the way home, he suddenly thought it would be better to buy some
fruits for his parents, so he found a good-looking fruit stall on the
roadside. He forgot what fruits his parents liked, so he squatted down
and tried to choose as many varieties as possible.&lt;/p&gt;
&lt;p&gt;&quot;Sir, how much is this pear per kilogram?&quot;&lt;/p&gt;
&lt;p&gt;This voice, just like the half-hour recording in his phone, is a
voice he will never forget. He looked up and saw the side face that had
been outlined countless times in his mind, as if he was stunned. He just
looked quietly without speaking or getting up. The woman who was buying
the pear took it and turned around, surprised to see the person staring
at her. But soon, it turned into a gentle smile.&lt;/p&gt;
&lt;p&gt;&quot;You&#39;re back!&quot;&lt;/p&gt;
&lt;p&gt;He stood up, straightened his clothes, and then spoke.&lt;/p&gt;
&lt;p&gt;&quot;Well, it&#39;s been a long time. I didn&#39;t expect you to keep your hair
so long.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Yes, ladies look better with long hair. You&#39;ve changed a lot
too.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Haha, handsome, right? Do you regret deciding to get rid of yourself
so early!&quot;&lt;/p&gt;
&lt;p&gt;He said in a joking tone, his eyes unconsciously glanced at the ring
on her left ring finger. As if the ring was too dazzling, he quickly
moved his gaze away.&lt;/p&gt;
&lt;p&gt;&quot;Huh, you&#39;re still so narcissistic.&quot;&lt;/p&gt;
&lt;p&gt;Her tone was a bit awkward, and he realized that some jokes couldn&#39;t
be made anymore. For a while, he didn&#39;t know what to say. Somehow, he
blurted out:&lt;/p&gt;
&lt;p&gt;&quot;You look pretty now.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Thank you.&quot; She didn&#39;t know what to say to him either. It&#39;s been too
long.&lt;/p&gt;
&lt;p&gt;He was very annoyed that he had brought the topic to a dead end. At
this time, she noticed the gray and white scarf he was wearing, which
didn&#39;t match his clothes at all. She suggested to find a topic:&lt;/p&gt;
&lt;p&gt;&quot;You&#39;re still so casual in your dress, and the scarf doesn&#39;t look
good.&quot;&lt;/p&gt;
&lt;p&gt;He was stunned for a moment, staring straight at her, then suddenly
laughed heartily, as if he had breathed a sigh of relief.&lt;/p&gt;
&lt;p&gt;&quot;But it&#39;s quite warm.&quot;&lt;/p&gt;
&lt;p&gt;For a moment, it seemed that a certain emptiness in his heart was
filled, and the stuck wheel of fate began to turn forward again. Perhaps
he had been waiting for this moment in front of her for the past five
years, to be able to laugh openly. The next moment, he was pushed
forward by fate, and he thought he should have the courage to step into
the future.&lt;/p&gt;
</description>
      <pubDate>Wed, 01 Jun 2011 00:00:00 GMT</pubDate>
      <dc:creator>Qiqi Jin</dc:creator>
      <guid>https://qiqijin.com/blog/posts/20110601-the_story_ending/</guid>
    </item>
  </channel>
</rss>
