-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
296 lines (161 loc) · 130 KB
/
atom.xml
File metadata and controls
296 lines (161 loc) · 130 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Comilao Learning</title>
<link href="https://comilao.github.io/atom.xml" rel="self"/>
<link href="https://comilao.github.io/"/>
<updated>2022-03-09T14:58:26.190Z</updated>
<id>https://comilao.github.io/</id>
<author>
<name>Ma Cong</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>Python max() vs if else</title>
<link href="https://comilao.github.io/python/research/4_python_max_ifelse/"/>
<id>https://comilao.github.io/python/research/4_python_max_ifelse/</id>
<published>2022-03-09T12:55:02.000Z</published>
<updated>2022-03-09T14:58:26.190Z</updated>
<content type="html"><![CDATA[<h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><p>This post discusses some interesting findings about <code>max()</code> and <code>if...else</code> when comparing 2 elements. I have this doubt while doing <a href="https://leetcode.com/problems/maximum-subarray/">LeetCode Problem 53. Maximum Subarray</a>.</p><span id="more"></span><h2 id="Introduction"><a href="#Introduction" class="headerlink" title="Introduction"></a>Introduction</h2><p>LeetCode Problem 53:</p><blockquote><p>Given an integer array <code>nums</code>, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. (A <strong>subarray</strong> is a <strong>contiguous</strong> part of an array.)</p></blockquote><p>My first attempt to this question is:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">solution</span>(<span class="params">nums</span>):</span></span><br><span class="line"> max_sum, temp = <span class="built_in">float</span>(<span class="string">'-inf'</span>), <span class="number">0</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> num <span class="keyword">in</span> nums:</span><br><span class="line"> temp = <span class="built_in">max</span>(temp + num, num)</span><br><span class="line"> max_sum = <span class="built_in">max</span>(max_sum, temp)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> max_sum</span><br></pre></td></tr></table></figure><p>This solution’s runtime is 1101ms which only beats 38.56% of Python3 submissions. To further optimize the runtime, I changed to the solution below:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">solution</span>(<span class="params">nums</span>):</span></span><br><span class="line"> max_sum, temp = <span class="built_in">float</span>(<span class="string">'-inf'</span>), <span class="number">0</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> num <span class="keyword">in</span> nums:</span><br><span class="line"> temp = <span class="built_in">max</span>(temp + num, num)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> temp > max_sum:</span><br><span class="line"> max_sum = temp</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> max_sum</span><br></pre></td></tr></table></figure><p>After reducing some unnecessary computations from <code>max()</code>, this solution has a runtime of 696ms which beats <strong>96.94%</strong> of Python3 submissions. Then I have a question of which method is faster when comparing just 2 elements.</p><h2 id="Experiment"><a href="#Experiment" class="headerlink" title="Experiment"></a>Experiment</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> time</span><br><span class="line"></span><br><span class="line">count, num_1, num_2 = <span class="number">10</span>**<span class="number">8</span>, <span class="number">1</span>, <span class="number">2</span></span><br><span class="line"></span><br><span class="line">start = time.time()</span><br><span class="line"><span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(count):</span><br><span class="line"> r = num_1 <span class="keyword">if</span> num_1 > num_2 <span class="keyword">else</span> num_2</span><br><span class="line">res_if = time.time() - start</span><br><span class="line"></span><br><span class="line">start = time.time()</span><br><span class="line"><span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(count):</span><br><span class="line"> r = <span class="built_in">max</span>(num_1, num_2)</span><br><span class="line">res_max = time.time() - start</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(<span class="string">f"res_if:<span class="subst">{res_if}</span>; res_max:<span class="subst">{res_max}</span>"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">#Result on my computer:</span></span><br><span class="line"><span class="comment">#res_if:9.846304178237915; res_max:23.544015884399414</span></span><br></pre></td></tr></table></figure><p>As we have observed, using <code>if...else</code> is much faster than <code>max()</code> when comparing 2 elements.</p><h2 id="Research"><a href="#Research" class="headerlink" title="Research"></a>Research</h2><p>My first thought is even for just two elements, <code>max()</code> still needs to loop through the two elements, which is a huge time for large number of calls, but for <code>if...else</code>, the comparison is direct and fast.</p><p>However, after research online, this <a href="https://stackoverflow.com/questions/56281691/why-is-max-function-so-much-slower-when-comparing-2-elements-vs-direct-compari">Stack Overflow Answer</a> provides another perspective:</p><blockquote><p>because <code>max</code> involves a dictionary lookup for the function name, then a function call, whereas direct <code><</code> operator does not.</p></blockquote><p>In his answer, the person also points out similar questions like <a href="https://stackoverflow.com/questions/36566331/why-does-dict-getkey-run-slower-than-dictkey">Why is <code>dict.get()</code> slower than <code>dict[key]</code>?</a> and <a href="https://stackoverflow.com/questions/30216000/why-is-faster-than-list">Why is [] faster than list()</a>. These two related questions have the similar answer, where a dictionary lookup for the function name is performed.</p><h2 id="Code-Practice"><a href="#Code-Practice" class="headerlink" title="Code Practice"></a>Code Practice</h2><p>To be honest, before noticing this performance issue on that LeetCode question, I was just blindly using <code>max()</code> for all scenarios. In the future, if I need to get the larger element from just 2 elements, I would use the <code>if...else</code> syntax for its slight faster speed. However, for getting the largest element from more than 2 elements, <code>max()</code> is preferred for readability purpose.</p>]]></content>
<summary type="html"><h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><p>This post discusses some interesting findings about <code>max()</code> and <code>if...else</code> when comparing 2 elements. I have this doubt while doing <a href="https://leetcode.com/problems/maximum-subarray/">LeetCode Problem 53. Maximum Subarray</a>.</p></summary>
<category term="python" scheme="https://comilao.github.io/categories/python/"/>
<category term="research" scheme="https://comilao.github.io/categories/python/research/"/>
<category term="python" scheme="https://comilao.github.io/tags/python/"/>
<category term="better code" scheme="https://comilao.github.io/tags/better-code/"/>
</entry>
<entry>
<title>iTerm2 with Oh My Zsh on Macbook</title>
<link href="https://comilao.github.io/miscellaneous/backup/backup_shell/"/>
<id>https://comilao.github.io/miscellaneous/backup/backup_shell/</id>
<published>2022-02-21T10:19:03.000Z</published>
<updated>2022-03-09T14:58:26.190Z</updated>
<content type="html"><![CDATA[<h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><p>This post is a backup referrence for me. It talks about iTerm2 with Oh My Zsh and its various plugins to build an awesome terminal.</p><span id="more"></span><h2 id="Prerequisite"><a href="#Prerequisite" class="headerlink" title="Prerequisite"></a>Prerequisite</h2><ul><li>git</li><li>homebrew</li></ul><h2 id="iTerm2"><a href="#iTerm2" class="headerlink" title="iTerm2"></a>iTerm2</h2><p>Download <a href="https://iterm2.com/">iTerm2</a>.</p><p>After installation, a <code>zsh</code> file should appear under <code>/bin</code> directory. To use <code>zsh</code> shell:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chsh -s /bin/zsh</span><br></pre></td></tr></table></figure><p>To change back to the default <code>bash</code> shell (But trust me, you don’t want to do it after using <code>zsh</code> with <code>Oh My Zsh</code>):</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chsh -s /bin/bash</span><br></pre></td></tr></table></figure><h2 id="Oh-My-Zsh"><a href="#Oh-My-Zsh" class="headerlink" title="Oh My Zsh"></a>Oh My Zsh</h2><p>Install <a href="https://github.com/ohmyzsh/ohmyzsh#basic-installation">Oh My Zsh</a>.</p><h3 id="Powerline"><a href="#Powerline" class="headerlink" title="Powerline"></a>Powerline</h3><p><a href="https://powerline.readthedocs.io/en/latest/overview.html">Powerline Homepage</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install powerline-status --user</span><br></pre></td></tr></table></figure><h3 id="Powerline-Fonts"><a href="#Powerline-Fonts" class="headerlink" title="Powerline Fonts"></a>Powerline Fonts</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/powerline/fonts.git --depth=1</span><br><span class="line">cd fonts</span><br><span class="line">./install.sh</span><br></pre></td></tr></table></figure><p>After installing Powerline Fonts, go to <code>iTerm2 -> Preferences -> Profiles -> Text</code> and look for <code>Font</code> to change it. I used <code>Meslo LG L for Powerline</code> L size font.</p><img src="https://i.imgur.com/JYKZvtG.png" alt="change_iTerm2_Font" width="80%" height="80%"><h3 id="Solarized-Color"><a href="#Solarized-Color" class="headerlink" title="Solarized Color"></a>Solarized Color</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/altercation/solarized</span><br><span class="line">cd solarized/iterm2-colors-solarized/</span><br><span class="line">open .</span><br></pre></td></tr></table></figure><p>This opens finder window, by double clicking <code>Solarized Dark.itermcolors</code> or <code>Solarized Light.itermcolors</code> file to install the color. Then go to <code>iTerm2 -> Preferences -> Profiles -> Colors -> Colors Presets</code> to choose you preferred color.</p><h3 id="Theme"><a href="#Theme" class="headerlink" title="Theme"></a>Theme</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/fcamblor/oh-my-zsh-agnoster-fcamblor.git</span><br><span class="line">cd oh-my-zsh-agnoster-fcamblor/</span><br><span class="line">./install</span><br></pre></td></tr></table></figure><p>The above command installs agnoster theme to Oh My Zsh themes. Look for <code>ZSH_THEME</code> in <code>~/.zshrc</code> to make the theme changes:</p><figure class="highlight diff"><figcaption><span>$HOME/.zshrc</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="deletion">- ZSH_THEME="robbyrussell"</span></span><br><span class="line"><span class="addition">+ ZSH_THEME="agnoster"</span></span><br></pre></td></tr></table></figure><p>After that, either relaunch <code>iTerm2</code> or with <code>source ~/.zshrc</code> command to apply the latest zsh configuration.</p><h3 id="Configurations"><a href="#Configurations" class="headerlink" title="Configurations"></a>Configurations</h3><h4 id="Natual-Text-Selection"><a href="#Natual-Text-Selection" class="headerlink" title="Natual Text Selection"></a>Natual Text Selection</h4><p>By default, word jumps (<code>option</code> + <code>→</code> or <code>←</code>) and word deletions (<code>option</code> + <code>backspace</code>) do not work. To enable them, go to <code>iTerm -> Preferences -> Profiles -> Keys -> Key Mappings</code>, look for <code>Presets...</code> and change to <code>Natural Text Editing</code>.</p><img src="https://i.imgur.com/hz6pwTm.png" alt="change_iTerm2_Natual_Text_Selection" width="80%" height="80%"><h4 id="Custom-Prompt"><a href="#Custom-Prompt" class="headerlink" title="Custom Prompt"></a>Custom Prompt</h4><p>By default, your terminal will now show “user@hostname” in the prompt, which might be too long. To remove this, you can add the line <code>DEFAULT_USER=$(whoami)</code> to <code>~/.zshrc</code>.</p><h4 id="Maximize-iTerm2"><a href="#Maximize-iTerm2" class="headerlink" title="Maximize iTerm2"></a>Maximize iTerm2</h4><p>Personally, I prefer to use a shell in the maximized window. Go to <code>iTerm -> Preferences -> Profiles -> Window</code>, look for the <code>Style</code> section and change to <code>Maximized</code> option.</p><h3 id="Plugins"><a href="#Plugins" class="headerlink" title="Plugins"></a>Plugins</h3><p>There are <a href="https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins">many many plugins</a> available for <code>Oh My Zsh</code>. For me, I use the following plugins:</p><figure class="highlight plaintext"><figcaption><span>$HOME/.zshrc</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">plugins=(</span><br><span class="line">git</span><br><span class="line">zsh-autosuggestions</span><br><span class="line">zsh-syntax-highlighting</span><br><span class="line">autojump</span><br><span class="line">k</span><br><span class="line">copydir</span><br><span class="line">copyfile</span><br><span class="line">copybuffer</span><br><span class="line">jsontools</span><br><span class="line">macos</span><br><span class="line">web-search</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p>Below are the web pages I have referred to when researching the top popular plugins:</p><ol><li><a href="https://www.youtube.com/watch?v=LEOqiyxx16c&t=256s">Top 10 Oh My Zsh Plugins For Productive Developers - Travis Media (The timestamp I used for this YouTube video shows all the plugins introduced in the video)</a></li><li><a href="https://safjan.com/top-popular-zsh-plugins-on-github/">Top popular Zsh plugins on GitHub - Krystian Safjan’s Blog</a></li></ol><p>For adding plugins, you could try to add them in the <code>~/.zshrc</code> configuration file and apply the settings by <code>source ~/.zshrc</code>. Some plugins are already installed by <code>Oh My Zsh</code>, those plugins are not installed will be prompted. You can install them accordingly. Installation guides for some plugins:</p><ul><li><a href="https://github.com/wting/autojump#installation">autojump</a></li><li><a href="https://github.com/zsh-users/zsh-autosuggestions/blob/master/INSTALL.md#oh-my-zsh">zsh-autosuggestions</a></li><li><a href="https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/INSTALL.md#oh-my-zsh">zsh-syntax-highlighting</a></li></ul><h4 id="zsh-autosuggestions"><a href="#zsh-autosuggestions" class="headerlink" title="zsh-autosuggestions"></a>zsh-autosuggestions</h4><p>For this plugin, the color for the auto suggested command lines might be too close to the background. To change auto suggested command color, go to <code>iTerm -> Preferences -> Profiles -> Colors -> ANSI Colors</code>, the first one in the Bright column is the auto suggested command color setting. For me, I used <code>80% Gray</code>.</p><img src="https://i.imgur.com/8fNOd4F.png" alt="iTerm2_change_auto_suggested_command_color" width="80%" height="80%"><h2 id="VS-Code-Issue"><a href="#VS-Code-Issue" class="headerlink" title="VS Code Issue"></a>VS Code Issue</h2><p>For the embedded terminal in VS Code, it might not properly represent the powerline prompt. To fix it, go to <code>Code -> Preferences -> Settings</code>, toggle to the JSON configuration file and change:</p><figure class="highlight diff"><figcaption><span>settings.json</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line">...</span><br><span class="line"> // zsh terminal and font fix for vscode</span><br><span class="line"><span class="addition">+ "terminal.integrated.defaultProfile.osx": "zsh",</span></span><br><span class="line"><span class="addition">+ "terminal.integrated.fontFamily": "Menlo for Powerline",</span></span><br><span class="line">...</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>Note:</strong> It is recommended to use the <strong>User</strong> level here, as we would like to apply these settings to the entire VS Code editor, not only a single project</p><h2 id="Referrence"><a href="#Referrence" class="headerlink" title="Referrence"></a>Referrence</h2><p><a href="https://apple.stackexchange.com/questions/136928/using-alt-cmd-right-left-arrow-in-iterm/218639#218639">Using Alt/Cmd + Right/Left Arrow in iTerm</a></p><p><a href="https://gist.github.com/kevin-smets/8568070">iTerm2 + Oh My Zsh + Solarized color scheme + Source Code Pro Powerline + Font Awesome + [Powerlevel10k] - (macOS)</a></p><p><a href="https://zhuanlan.zhihu.com/p/37195261">iTerm2 + Oh My Zsh (In Chinese)</a></p><p><a href="https://dev.to/mattstratton/making-powerline-work-in-visual-studio-code-terminal-1m7">Fix powerline in VS Code</a></p>]]></content>
<summary type="html"><h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><p>This post is a backup referrence for me. It talks about iTerm2 with Oh My Zsh and its various plugins to build an awesome terminal.</p></summary>
<category term="miscellaneous" scheme="https://comilao.github.io/categories/miscellaneous/"/>
<category term="backup" scheme="https://comilao.github.io/categories/miscellaneous/backup/"/>
<category term="backup" scheme="https://comilao.github.io/tags/backup/"/>
</entry>
<entry>
<title>Precision and representation of number in Python</title>
<link href="https://comilao.github.io/python/research/2_python_precision/"/>
<id>https://comilao.github.io/python/research/2_python_precision/</id>
<published>2022-02-12T14:34:41.000Z</published>
<updated>2022-02-13T06:36:57.294Z</updated>
<content type="html"><![CDATA[<h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><blockquote><p>Python can handle precision of floating point numbers</p></blockquote><p>That’s one of the common findings from Google when searching “Precision in Python”.</p><p>In one of my company’s projects, I need to either multiply a number or divide a number by 10^8, and return the result in string format. In primary school Math class, we can move the decimal point forward/backward and add/remove zero accordingly along the way. However, when I start doing this task with <code>*</code> or <code>\</code> directly and apply <code>str()</code> to the result in Python, things began to get really complicated and interesting, results like <code>"0.08353999999999999"</code> (a precision issue) and <code>"1e-08"</code> (a representation issue) are returned.</p><span id="more"></span><h2 id="Precision-Issue"><a href="#Precision-Issue" class="headerlink" title="Precision Issue"></a>Precision Issue</h2><p>From <a href="https://docs.python.org/3/tutorial/floatingpoint.html">Floating Point Arithmetic: Issues and Limitations</a></p><blockquote><p>Computer hardware is base 2, hence for the fraction 1/3, it is approximately <code>0.3</code>, <code>0.33</code> or <code>0.333</code>, but no matter how many digits we’are willing to write down, the result will never be exactly 1/3, but will be an increasingly better approximation of 1/3.</p></blockquote><h3 id="Inaccurate-floating-point-calculation"><a href="#Inaccurate-floating-point-calculation" class="headerlink" title="Inaccurate floating point calculation"></a>Inaccurate floating point calculation</h3><p>Consider this calculation in Python:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="number">8.354</span>/<span class="number">100</span></span><br><span class="line"><span class="number">0.08353999999999999</span></span><br></pre></td></tr></table></figure><h3 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h3><p>Since we cannot store an infinite number in the memory due to how a base-10 number is represented in base-2, especially for floating point. The issue now becomes up to how many decimal points do we want to keep the accuracy.</p><h4 id="1-With-decimal"><a href="#1-With-decimal" class="headerlink" title="1. With decimal"></a>1. With <code>decimal</code></h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> decimal <span class="keyword">import</span> Decimal, localcontext</span><br><span class="line"></span><br><span class="line"><span class="keyword">with</span> localcontext() <span class="keyword">as</span> ctx:</span><br><span class="line"> ctx.prec = <span class="number">10</span> <span class="comment"># or a even higher precision</span></span><br><span class="line"> res = Decimal(value=<span class="string">"0.854"</span>, context=ctx) / <span class="number">100</span> <span class="comment"># res is 0.00854 with high precision</span></span><br><span class="line"></span><br><span class="line">res = +res <span class="comment"># res is 0.00854 still, but rounded back to the default precision</span></span><br></pre></td></tr></table></figure><p>I got this idea from <a href="https://github.com/ethereum/eth-utils/blob/master/eth_utils/currency.py">ethereum currency conversion</a>. Basically we set a sufficiently high precision and perform a high precision calculation (999 is used for the Ethereum currency conversion). Do note that in order to preserve the precision of the constructed decimal object, the <code>value</code> parameter is better to be <code>str</code> type then <code>float</code>.</p><p>(Try with <code>Decimal(value=0.854, context=ctx)</code> and have a look🤪)</p><p>I also did some further readings on <code>Decimal</code> library, it is mainly used for the banking and financial industry, since accuracy is very important. However, there is a tradeoff of slow performance by using this library. (I once read an old news, a bank employee wrote a code to transfer the tiny bits beyond the displayed balance to his own account, this employee made lots of money from it because of the large amount of daily transactions.)</p><h4 id="2-With-round"><a href="#2-With-round" class="headerlink" title="2. With round()"></a>2. With <code>round()</code></h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">d = <span class="number">8.354</span> / <span class="number">100</span></span><br><span class="line"><span class="built_in">print</span>(<span class="built_in">round</span>(d, <span class="number">10</span>))</span><br></pre></td></tr></table></figure><p><code>round()</code> rounds a number to a given precision in decimal digits.</p><h3 id="Discussion"><a href="#Discussion" class="headerlink" title="Discussion"></a>Discussion</h3><p>I choose the Ethereum method over <code>round()</code>, as the input value of my conversion function could be string type. Converting a string type to a type that <code>round()</code> supports requires an extra step, which might cause some unexpected behaviours.</p><h2 id="Representation-Issue"><a href="#Representation-Issue" class="headerlink" title="Representation Issue"></a>Representation Issue</h2><p>In my case, I need to return the string type of the floating point result as it is, instead of scientific notation. This means result of <code>1 / 10 **8</code> should be returned as <code>"0.00000001"</code> not <code>"1e-08"</code>.</p><h3 id="Solution-1"><a href="#Solution-1" class="headerlink" title="Solution"></a>Solution</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> decimal <span class="keyword">import</span> Decimal, localcontext</span><br><span class="line"></span><br><span class="line"><span class="keyword">with</span> localcontext() <span class="keyword">as</span> ctx:</span><br><span class="line"> ctx.prec = <span class="number">10</span></span><br><span class="line"> num = Decimal(value=<span class="string">"1"</span>, context=ctx) / <span class="number">10</span>**<span class="number">10</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(<span class="string">"%f"</span> % num) <span class="comment"># 0.000000</span></span><br><span class="line"><span class="built_in">print</span>(<span class="string">f"<span class="subst">{num:f}</span>"</span>) <span class="comment"># 0.0000000001</span></span><br><span class="line"><span class="built_in">print</span>(<span class="string">"{:f}"</span>.<span class="built_in">format</span>(num)) <span class="comment"># 0.0000000001</span></span><br></pre></td></tr></table></figure><p>Note: <code>.format()</code> uses full precision while <code>%f</code> defaults to a precision of 6.</p><h3 id="Discussion-1"><a href="#Discussion-1" class="headerlink" title="Discussion"></a>Discussion</h3><p>Division in Python is tricky, as the result is always <code>float</code> type, even for integer division with no remainder, hence a tidy up step is neeed.</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">res = <span class="number">100</span> / <span class="number">10</span> <span class="comment"># res is 10.0 float type</span></span><br><span class="line">res = <span class="built_in">str</span>(res) <span class="comment"># res is "10.0" str type</span></span><br><span class="line">res = res.rstrip(<span class="string">"0"</span>).rstrip(<span class="string">"."</span>) <span class="comment"># res is "10" str type</span></span><br></pre></td></tr></table></figure><h2 id="Other-Methods"><a href="#Other-Methods" class="headerlink" title="Other Methods"></a>Other Methods</h2><blockquote><p>In primary school Math class, we can move the decimal point forward/backward and add/remove zero accordingly along the way.</p></blockquote><p>To tackle ths problem, after discussing it with a friend, he mentioned the pure string manipulation solution just like how we do it in Math class, since the calculation involved is just multiplication or division by 10^x.</p><p>I did not implement this solution though, I just thought about it roughly.</p><p>For multiplication of <code>10 ^8</code></p><ol><li><p>If string does not contain any decimal points, just add 8 zeros at the back of the string, done</p></li><li><p>If string contains 1 decimal point:</p><ol><li>Add 8 zeros at the back of the string</li><li>Move <code>"."</code> from the current index to the current index + 8 position</li><li>Tidy up the result by <code>result.rstrip("0").rstrip(".")</code></li></ol><p> (<strong>Note:</strong> Do not do <code>result.rstrip("0.")</code>, you may try <code>"10.00".rstrip("0.")</code>🤪)</p></li><li><p>If string contains more than 1 decimal point, this is an invalid input❌</p></li></ol><p>For division of <code>10 ^8</code></p><ol><li>Check string contains 0 or 1 <code>"."</code>, else it is an invalid input❌</li><li>Add 8 zeros at the front of the string</li><li>Move <code>"."</code> from the current index to the current index - 8 position</li><li>Tidy up the result by <code>result.lstrip("0")</code></li><li>If index 0 of the result is <code>"."</code>, add a <code>"0"</code> in front of the result</li></ol><h2 id="Referrence"><a href="#Referrence" class="headerlink" title="Referrence"></a>Referrence</h2><p><a href="https://docs.python.org/3/tutorial/floatingpoint.html">Floating Point Arithmetic: Issues and Limitations</a></p><p><a href="https://github.com/ethereum/eth-utils/blob/master/eth_utils/currency.py">Ethereum Utilities Currency Conversion Code</a></p><p><a href="https://stackoverflow.com/questions/22490568/converting-a-very-small-python-decimal-into-a-non-scientific-notation-string">Stackoverflow: Converting a very small python Decimal into a non-scientific notation string</a></p>]]></content>
<summary type="html"><h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><blockquote>
<p>Python can handle precision of floating point numbers</p>
</blockquote>
<p>That’s one of the common findings from Google when searching “Precision in Python”.</p>
<p>In one of my company’s projects, I need to either multiply a number or divide a number by 10^8, and return the result in string format. In primary school Math class, we can move the decimal point forward/backward and add/remove zero accordingly along the way. However, when I start doing this task with <code>*</code> or <code>\</code> directly and apply <code>str()</code> to the result in Python, things began to get really complicated and interesting, results like <code>&quot;0.08353999999999999&quot;</code> (a precision issue) and <code>&quot;1e-08&quot;</code> (a representation issue) are returned.</p></summary>
<category term="python" scheme="https://comilao.github.io/categories/python/"/>
<category term="research" scheme="https://comilao.github.io/categories/python/research/"/>
<category term="python" scheme="https://comilao.github.io/tags/python/"/>
<category term="precision" scheme="https://comilao.github.io/tags/precision/"/>
<category term="floating-point" scheme="https://comilao.github.io/tags/floating-point/"/>
</entry>
<entry>
<title>Mypy in Python</title>
<link href="https://comilao.github.io/python/setup/1_python_mypy/"/>
<id>https://comilao.github.io/python/setup/1_python_mypy/</id>
<published>2022-02-09T12:25:01.000Z</published>
<updated>2022-02-10T16:08:39.425Z</updated>
<content type="html"><![CDATA[<h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><p>Python does not have the ability to explicitly specify variable types. All variable types are inferred based on assignment. This may lead to runtime error such as <code>"str" + 1</code> (this only produces unintended/unexpected result in JavaScript though), it also prevents editor to offer valuable suggestions.</p><p><a href="https://mypy.readthedocs.io/en/stable/">Mypy</a> is a static type checker. In one of my company’s project, I noticed <code>mypy.ini</code> sitting in the project directory, but not being utilised. After some research on <code>mypy</code>, I decided to add its support together with <a href="https://pre-commit.com/">pre-commit</a>. This blog post discusses <code>mypy</code> usage briefly, but focus more on the configurations of files to be checked or excluded in the context of <code>mypy</code> and <code>pre-commit</code> hook configuration.</p><span id="more"></span><h2 id="Usage"><a href="#Usage" class="headerlink" title="Usage"></a>Usage</h2><h3 id="Setup-Demo"><a href="#Setup-Demo" class="headerlink" title="Setup Demo"></a>Setup Demo</h3><p>Demo project structure.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── project</span><br><span class="line">│ ├── pyproject.toml</span><br><span class="line">│ ├── mypy.ini</span><br><span class="line">│ ├── main.py</span><br><span class="line">│ └── module</span><br><span class="line">│ ├── __init__.py</span><br><span class="line">│ ├── coingecko_api.py</span><br><span class="line">│ └── github_api.py</span><br><span class="line">│</span><br></pre></td></tr></table></figure><p>Dependency required for the demo.</p><figure class="highlight toml"><figcaption><span>pyproject.toml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># partial pyproject.toml is shown</span></span><br><span class="line"></span><br><span class="line"><span class="section">[tool.poetry.dependencies]</span></span><br><span class="line"><span class="attr">python</span> = <span class="string">"^3.9"</span></span><br><span class="line"><span class="attr">requests</span> = <span class="string">"^2.27.1"</span></span><br><span class="line"></span><br><span class="line"><span class="section">[tool.poetry.dev-dependencies]</span></span><br><span class="line"><span class="attr">mypy</span> = <span class="string">"^0.931"</span></span><br><span class="line"><span class="attr">pre-commit</span> = <span class="string">"^2.17.0"</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ...</span></span><br></pre></td></tr></table></figure><p>Files</p><figure class="highlight ini"><figcaption><span>./mypy.ini</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">[mypy]</span></span><br><span class="line"><span class="attr">python_version</span> = <span class="number">3.9</span></span><br></pre></td></tr></table></figure><figure class="highlight python"><figcaption><span>./main.py</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">dummy_func</span>(<span class="params">v: <span class="built_in">str</span></span>) -> <span class="built_in">str</span>:</span></span><br><span class="line"> <span class="keyword">return</span> v</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:</span><br><span class="line"> dummy_func(<span class="string">"1"</span>)</span><br></pre></td></tr></table></figure><figure class="highlight python"><figcaption><span>./module/__init__.py</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> .coingecko_api <span class="keyword">import</span> CoinGeckoAPI</span><br><span class="line"><span class="keyword">from</span> .github_api <span class="keyword">import</span> get_github_user</span><br><span class="line"></span><br><span class="line">__all__ = [<span class="string">"CoinGeckoAPI"</span>, <span class="string">"get_github_user"</span>]</span><br></pre></td></tr></table></figure><figure class="highlight python"><figcaption><span>./module/coingecko_api.py</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CoinGeckoAPI</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self, dummy_int: <span class="built_in">int</span></span>) -> <span class="literal">None</span>:</span></span><br><span class="line"> self.dummy_str: <span class="built_in">str</span> = dummy_int</span><br><span class="line"></span><br><span class="line"><span class="meta"> @property</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">dummy_str</span>(<span class="params">self</span>) -> <span class="built_in">str</span>:</span></span><br><span class="line"> <span class="keyword">return</span> self._dummy_str</span><br><span class="line"></span><br><span class="line"><span class="meta"> @dummy_str.setter</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">dummy_str</span>(<span class="params">self, dummy_int: <span class="built_in">int</span></span>) -> <span class="literal">None</span>:</span></span><br><span class="line"> self._dummy_str = <span class="string">"000"</span> + <span class="built_in">str</span>(dummy_int)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__eq__</span>(<span class="params">self, __o: <span class="string">"CoinGeckoAPI"</span></span>) -> <span class="built_in">bool</span>:</span></span><br><span class="line"> <span class="keyword">return</span> self.dummy_str == __o.dummy_str</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">get_bitcoin_price</span>(<span class="params">self</span>):</span></span><br><span class="line"> r = requests.get(</span><br><span class="line"> <span class="string">"https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd"</span></span><br><span class="line"> )</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> r.json()</span><br></pre></td></tr></table></figure><figure class="highlight python"><figcaption><span>./module/github_api.py</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_github_user</span>():</span></span><br><span class="line"> r = requests.get(<span class="string">"https://api.github.com/user"</span>, auth=(<span class="string">"user"</span>, <span class="string">"pass"</span>))</span><br><span class="line"> <span class="keyword">return</span> r.status_code</span><br></pre></td></tr></table></figure><h3 id="Run-type-checking"><a href="#Run-type-checking" class="headerlink" title="Run type checking"></a>Run type checking</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> At project root</span></span><br><span class="line">mypy .</span><br></pre></td></tr></table></figure><p>After running above command, <code>mypy .</code> should complain these 3 types of errors:</p><ol><li>Library stubs not installed for “requests”</li><li>Incompatible types in assignment (expression has type “int”, variable has type “str”)</li><li>Argument 1 of “<strong>eq</strong>“ is incompatible with supertype “object”; supertype defines the argument type as “object”</li></ol><h3 id="Missing-library-stubs"><a href="#Missing-library-stubs" class="headerlink" title="Missing library stubs"></a>Missing library stubs</h3><p>For this error, mypy already shows <code>Hint: "python3 -m pip install types-requests"</code> to install the missing type dependency, in this case <code>types-requests</code>.</p><p>Hints offered are quite accurate in my experience, except the case for <code>grpc</code> for my company’s project, which requires <code>grpc-stubs</code>.</p><h3 id="Incompatible-type"><a href="#Incompatible-type" class="headerlink" title="Incompatible type"></a>Incompatible type</h3><p>For this error, <code>mymy</code> is complaining for this line in <code>./module/coingecko_api.py</code>:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">self.dummy_str: <span class="built_in">str</span> = dummy_int</span><br></pre></td></tr></table></figure><p><code>mypy</code> thinks I try to assign <code>int</code> type to <code>str</code>, despite I used type conversion inside setter annotated by <code>@dummy_str.setter</code>. This is unfortunately not solved at the time of writting, you may watch this <a href="https://github.com/python/mypy/issues/3004">issue</a>.</p><p>To make <code>mypy</code> happy, we have no choice but to ignore it by:</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="deletion">- self.dummy_str: str = dummy_int</span></span><br><span class="line"><span class="addition">+ self.dummy_str: str = dummy_int # type:ignore</span></span><br></pre></td></tr></table></figure><h3 id="“-eq-”-input-type"><a href="#“-eq-”-input-type" class="headerlink" title="“__eq__()” input type"></a>“__eq__()” input type</h3><p>For this error, <code>mypy</code> again provides a very useful hint message:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">def __eq__(self, other: object) -> bool:</span><br><span class="line"> if not isinstance(other, CoinGeckoAPI):</span><br><span class="line"> return NotImplemented</span><br><span class="line"> return <logic to compare two instances></span><br></pre></td></tr></table></figure><h2 id="Configuration"><a href="#Configuration" class="headerlink" title="Configuration"></a>Configuration</h2><p>After making relevant changes above, running <code>mypy .</code> should succeed. Now I will discuss about the configuration files.</p><p>In order to discuss configurations for files to be checked or ignored, we need to add <code>pre-commit</code> configuration to <code>.pre-commit-config.yaml</code>:</p><figure class="highlight yaml"><figcaption><span>.pre-commit-config.yaml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">repos:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">repo:</span> <span class="string">https://github.com/pre-commit/mirrors-mypy</span></span><br><span class="line"> <span class="attr">rev:</span> <span class="string">v0.931</span> <span class="comment"># Use the sha / tag you want to point at</span></span><br><span class="line"> <span class="attr">hooks:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">mypy</span></span><br></pre></td></tr></table></figure><h3 id="Missing-stubs-again"><a href="#Missing-stubs-again" class="headerlink" title="Missing stubs again?"></a>Missing stubs again?</h3><p>After that, running <code>pre-commit run --all-files</code> should report one error about <code>Missing library stubs</code> discussed earlier, despite <code>mypy .</code> reports no error! (<strong>Note:</strong> You need to add files to version control for <code>pre-commit</code> to work, a simple <code>git add .</code> will work, there is no need to commit the changes though.)</p><p>This is because type dependencies need to be added explicitly for <code>mypy</code> hook in <code>.pre-commit-config.yaml</code>:</p><figure class="highlight diff"><figcaption><span>.pre-commit-config.yaml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">repos:</span><br><span class="line"> rev: v0.931 # Use the sha / tag you want to point at</span><br><span class="line"> hooks:</span><br><span class="line"> - id: mypy</span><br><span class="line"><span class="addition">+ additional_dependencies:</span></span><br><span class="line"><span class="addition">+ - types-requests==2.27.9 # Note the different version syntax from poetry configuration</span></span><br></pre></td></tr></table></figure><p>After making the changes above, <code>pre-commit run --all-files</code> should report no errors.</p><h3 id="Before-moving-on"><a href="#Before-moving-on" class="headerlink" title="Before moving on"></a>Before moving on</h3><p>For the following sections, please make some changes to break <code>mypy</code> type checking, for me, I did the following evil code:</p><figure class="highlight diff"><figcaption><span>./main.py</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">if __name__ == "__main__":</span><br><span class="line"><span class="deletion">- dummy_func("1")</span></span><br><span class="line"><span class="addition">+ dummy_func(1)</span></span><br></pre></td></tr></table></figure><p>and</p><figure class="highlight diff"><figcaption><span>./module/coingecko_api.py</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="deletion">- def __eq__(self, __o: object) -> bool:</span></span><br><span class="line"><span class="addition">+ def __eq__(self, __o: "CoinGeckoAPI") -> bool:</span></span><br><span class="line"><span class="deletion">- if not isinstance(__o, CoinGeckoAPI):</span></span><br><span class="line"><span class="deletion">- return NotImplemented</span></span><br><span class="line"> return self.dummy_str == __o.dummy_str</span><br></pre></td></tr></table></figure><p>Running <code>mypy .</code> and <code>pre-commit run --all-files</code> should both report the same 2 errors now.</p><h3 id="Files-to-check"><a href="#Files-to-check" class="headerlink" title="Files to check"></a>Files to check</h3><p>For <code>mypy</code> to check only module directory:</p><figure class="highlight diff"><figcaption><span>mypy.ini</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[mypy]</span><br><span class="line">python_version = 3.9</span><br><span class="line"><span class="addition">+ files = module/</span></span><br></pre></td></tr></table></figure><p>Running <code>mypy</code> now (instead of <code>mypy .</code> earlier) should only report <strong>one</strong> error from <code>module</code> directory. However, running <code>pre-commit run --all-files</code> still reports <strong>two</strong> errors. That is because <code>mypy</code> hook in <code>pre-commit</code> does not read <code>files</code> configuration from <code>mypy.ini</code>, we need to make the following changes in <code>.pre-commit-config.yaml</code>:</p><figure class="highlight diff"><figcaption><span>.pre-commit-config.yaml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">repos:</span><br><span class="line">\- repo: https://github.com/pre-commit/mirrors-mypy</span><br><span class="line"> rev: v0.931</span><br><span class="line"> hooks:</span><br><span class="line"> - id: mypy</span><br><span class="line"><span class="addition">+ files: ^module/</span></span><br><span class="line"> additional_dependencies:</span><br><span class="line"> - types-requests==2.27.9</span><br></pre></td></tr></table></figure><p>Note the different syntax for <code>files</code> configuration in <code>mypy.ini</code> and <code>mypy</code> hook in <code>.pre-commit-config.yaml</code>. Refer to <a href="https://mypy.readthedocs.io/en/stable/config_file.html#confval-files">mypy configuration file</a> for more information about <code>files</code> configuration in <code>mypy.ini</code>; as for <code>.pre-commit-config.yaml</code>, it is just regex, which is much simpler.</p><p>(Remember to revert the changes for <code>files</code> configuration made in this section before moving on to the next section.)</p><h3 id="Files-to-exclude"><a href="#Files-to-exclude" class="headerlink" title="Files to exclude"></a>Files to exclude</h3><p>For <code>mypy</code> to exclude <code>module</code> directory:</p><figure class="highlight diff"><figcaption><span>mypy.ini</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[mypy]</span><br><span class="line">python_version = 3.9</span><br><span class="line"><span class="addition">+ exclude = module/</span></span><br></pre></td></tr></table></figure><p>To add more directories or files to exclude, the <a href="https://mypy.readthedocs.io/en/stable/config_file.html#confval-exclude">exclude</a> configuration looks like:</p><figure class="highlight diff"><figcaption><span>mypy.ini</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[mypy]</span><br><span class="line">python_version = 3.9</span><br><span class="line"><span class="addition">+exclude = (?x)(</span></span><br><span class="line"><span class="addition">+ module/</span></span><br><span class="line"><span class="addition">+ | main.py$ # the `)` could also be put immediately after `$` like `$)`</span></span><br><span class="line"><span class="addition">+ ) # else note this is not a typo, at least one space is needed before `)`, else parsing error occurs</span></span><br></pre></td></tr></table></figure><p>Since everything is excluded, now running <code>mypy .</code> should check no files!</p><p>As usual, running <code>pre-commit run --all-files</code> now checks all 4 Python files and report 2 errors, because <code>mypy</code> hook in <code>pre-commit run --all-files</code> does not read <code>exclude</code> configuration in <code>mypy.ini</code>. Add <code>exclude</code> configuration to <code>.pre-commit-config.yaml</code>:</p><figure class="highlight diff"><figcaption><span>.pre-commit-config.yaml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">repos:</span><br><span class="line">\- repo: https://github.com/pre-commit/mirrors-mypy</span><br><span class="line"> rev: v0.931</span><br><span class="line"> hooks:</span><br><span class="line"> - id: mypy</span><br><span class="line"><span class="addition">+ exclude: module</span></span><br><span class="line"> additional_dependencies:</span><br><span class="line"> - types-requests==2.27.9</span><br></pre></td></tr></table></figure><p>Running <code>pre-commit run --all-files</code> should only report <strong>one</strong> error from <code>main.py</code> now. Again, the <code>exclude</code> configuration for <code>mypy</code> hook in <code>pre-commit</code> is using regex ^_^</p><h3 id="Other-configurations"><a href="#Other-configurations" class="headerlink" title="Other configurations?"></a>Other configurations?</h3><p>From my trial and error, <code>mypy</code> hook respects type check configurations like <code>disallow_any_unimported</code> and per-module options under syntax like<code>[mypy-mymodule]</code>.</p><h2 id="Conclusion"><a href="#Conclusion" class="headerlink" title="Conclusion"></a>Conclusion</h2><p>As one of the comment from <a href="https://github.com/pre-commit/mirrors-mypy/issues/24#issuecomment-830630682">this issue</a>:</p><blockquote><p>i’ve got the same problem. it’s annoying to have to have two sources of truth for which files to include (mypy.ini and pre-commit config)</p></blockquote><p>I also found it is annoying to have configurations for the same plugin at different places, but sadly this is the case for <code>mypy</code>.</p><p>For me, I would put <code>files</code>, <code>exclude</code> and <code>additional_dependencies</code> configurations in <code>.pre-commit-config.yaml</code>, leave the rest in <code>mypy.ini</code> and always run <code>pre-commit run --all-files</code> to check instead of <code>mypy</code> command. Add <code>pre-commit</code> to git hook scripts locally so that it get executed automatically on <code>git commit</code> and put it as part of the CI process if possible.</p><h2 id="Referrence"><a href="#Referrence" class="headerlink" title="Referrence"></a>Referrence</h2><p><a href="https://stackoverflow.com/questions/37557411/why-does-defining-the-argument-types-for-eq-throw-a-mypy-type-error">Why does defining the argument types for __eq__ throw a MyPy type error?</a></p><p><a href="https://github.com/python/mypy/issues/3004">What to do about setters of a different type than their property?</a></p><p><a href="https://github.com/pre-commit/mirrors-mypy/issues/24">“files” configuration in mypy.ini is ignored for mirrors-mypy</a></p><p><a href="https://mypy.readthedocs.io/">mypy documentation</a></p>]]></content>
<summary type="html"><h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><p>Python does not have the ability to explicitly specify variable types. All variable types are inferred based on assignment. This may lead to runtime error such as <code>&quot;str&quot; + 1</code> (this only produces unintended/unexpected result in JavaScript though), it also prevents editor to offer valuable suggestions.</p>
<p><a href="https://mypy.readthedocs.io/en/stable/">Mypy</a> is a static type checker. In one of my company’s project, I noticed <code>mypy.ini</code> sitting in the project directory, but not being utilised. After some research on <code>mypy</code>, I decided to add its support together with <a href="https://pre-commit.com/">pre-commit</a>. This blog post discusses <code>mypy</code> usage briefly, but focus more on the configurations of files to be checked or excluded in the context of <code>mypy</code> and <code>pre-commit</code> hook configuration.</p></summary>
<category term="python" scheme="https://comilao.github.io/categories/python/"/>
<category term="setup" scheme="https://comilao.github.io/categories/python/setup/"/>
<category term="python" scheme="https://comilao.github.io/tags/python/"/>
<category term="mypy" scheme="https://comilao.github.io/tags/mypy/"/>
<category term="pre-commit" scheme="https://comilao.github.io/tags/pre-commit/"/>
<category term="mypy configuration" scheme="https://comilao.github.io/tags/mypy-configuration/"/>
<category term="pre-commit configuration" scheme="https://comilao.github.io/tags/pre-commit-configuration/"/>
</entry>
<entry>
<title>Hexo with Image Hosting</title>
<link href="https://comilao.github.io/setup/hexo/hexo_with_image/"/>
<id>https://comilao.github.io/setup/hexo/hexo_with_image/</id>
<published>2022-01-29T11:01:02.000Z</published>
<updated>2022-01-30T06:36:44.000Z</updated>
<content type="html"><</code> will be inserted once the upload is done</li></ol><h3 id="Issues-Huge-Image"><a href="#Issues-Huge-Image" class="headerlink" title="Issues - Huge Image"></a>Issues - Huge Image</h3><p>Normally I might need to upload some screenshots, and they have quite high resolutions, hence the image inserted takes a lot space, which reduces the reading experience. I found hexo supports html img tag.</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"https://link"</span> <span class="attr">alt</span>=<span class="string">"display text when link died"</span> <span class="attr">width</span>=<span class="string">"40%"</span> <span class="attr">height</span>=<span class="string">"40%"</span>></span></span></span><br></pre></td></tr></table></figure><p>PicGo extension also supports <code>Custom Output Format</code>. For me I changed the output format to <code><img src="${url}" alt="${uploadedName}" width="" height=""></code>.</p><p>However, this type of markdown syntax conflicts with markdownlint’s <a href="https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md033">MD033-Inline HTML</a>. To allow <code>img</code> tag for this rule, change markdownlint config like below.</p><figure class="highlight json"><figcaption><span>.vscode/settings.json</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"markdownlint.config"</span>: {</span><br><span class="line"> <span class="attr">"MD033"</span>: {</span><br><span class="line"> <span class="attr">"allowed_elements"</span>: [</span><br><span class="line"> <span class="string">"img"</span></span><br><span class="line"> ]</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Referrence"><a href="#Referrence" class="headerlink" title="Referrence"></a>Referrence</h2><p><a href="https://picgo.github.io/PicGo-Doc/en/guide/config.html#imgur-img">Configure imgur for PicGo VS Code Extension</a></p><p><a href="https://github.com/DavidAnson/markdownlint/blob/f87f9d080002281d96ac32f119d8c99c028a6ddb/test/inline_html-allowed_elements.json">Allowing elements for inline HTML for markdownlint</a></p>]]></content>
<summary type="html"><h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><p>Sometimes, I might need to insert images into a blog post. The pain point I had earlier is storing image somewhere and copy that path inside the blog post in an organized manner. After some research online, I decided to use an image hosing service (<a href="https://imgur.com/">imgur</a>) with a VS Code extension (<a href="https://marketplace.visualstudio.com/items?itemName=Spades.vs-picgo">picGo</a>) to faciliate the upload and link generation process.</p></summary>
<category term="setup" scheme="https://comilao.github.io/categories/setup/"/>
<category term="hexo" scheme="https://comilao.github.io/categories/setup/hexo/"/>
<category term="setup" scheme="https://comilao.github.io/tags/setup/"/>
<category term="hexo" scheme="https://comilao.github.io/tags/hexo/"/>
<category term="image hosting" scheme="https://comilao.github.io/tags/image-hosting/"/>
</entry>
<entry>
<title>Markdown Syntax</title>
<link href="https://comilao.github.io/miscellaneous/markdown_syntax/"/>
<id>https://comilao.github.io/miscellaneous/markdown_syntax/</id>
<published>2022-01-26T12:44:32.000Z</published>
<updated>2022-01-25T16:00:00.000Z</updated>
<content type="html"><![CDATA[<h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><blockquote><p>Hmm, another article talking about Markdown?</p></blockquote><p>Well, I am not going through the Markdown syntax one by one in this article, I am pretty sure they are quite easy to master after some practices. But instead, I will talk about some hidden parts (at least to me😅) of the Markdown syntax, especially after using <a href="https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint">markdownlint</a> extension.</p><p>If you are looking for a quick Markdown Cheat Sheet, you could refer to <a href="https://www.markdownguide.org/cheat-sheet/">Markdown Guide</a>. In summary, all basic syntax are supported for hexo with next theme (I am not sure whether theme matters, but let’s be precise); for the extended syntax, <code>Table</code>, <code>Fenced Code Block</code>, <code>Definition List</code>, <code>Strikethrough</code> and <code>Task List</code> (not sure the purpose of this in a blog article though) are supported. That’s good enough for writting a good blog article with Markdown, hooray🎉.</p><span id="more"></span><hr><h2 id="Horizontal-Line"><a href="#Horizontal-Line" class="headerlink" title="Horizontal Line"></a>Horizontal Line</h2><p>The default <code>Horizontal Line</code> from VS Code quick suggestion is <code>----------</code>, which conflicts with markdownlint extension rule <a href="https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md035">MD035 - Horizontal rule style</a>. Hence it is either to ignore the rule (and break it) or to add another snippet to obey the rule.</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"hr line"</span>: {</span><br><span class="line"> <span class="comment">// to obey markdownlint's MD035 - Horizontal rule style</span></span><br><span class="line"> <span class="attr">"description"</span>: <span class="string">"Insert consistent hr"</span>,</span><br><span class="line"> <span class="attr">"prefix"</span>: <span class="string">"hr"</span>,</span><br><span class="line"> <span class="attr">"body"</span>: <span class="string">"---"</span></span><br><span class="line">},</span><br></pre></td></tr></table></figure><hr><h2 id="Fenced-Code-Block"><a href="#Fenced-Code-Block" class="headerlink" title="Fenced Code Block"></a>Fenced Code Block</h2><h3 id="Code-Block-Language"><a href="#Code-Block-Language" class="headerlink" title="Code Block Language"></a>Code Block Language</h3><p>With markdownlint extension rule <a href="https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md040">MD040 - Fenced code blocks should have a language specified</a>, we are required to specify the language for a Fenced Code Block.</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="code">```JavaScript</span></span><br><span class="line"><span class="code">let var = 1;</span></span><br><span class="line"><span class="code">const func = () => "func";</span></span><br><span class="line"><span class="code">```</span></span><br></pre></td></tr></table></figure><p>Then the issue is, what are the language that we can specify? The complete list is <a href="https://github.com/github/linguist/blob/master/lib/linguist/languages.yml">here</a>.</p><p>I know it is a huge list! But the rule seems to be quite lenient for detecting the name of the language. For example, <code>JavaScript</code> could be written as <code>js</code>, <code>JS</code>, <code>JavaScript</code> or <code>javascript</code> and <code>Python</code> could be written as <code>py</code>, <code>python</code> or <code>Python</code>. It won’t affect the rendered HTML by GitHub or Hexo and VS Code is also able to highlight the syntax.</p><h3 id="Bash-Script"><a href="#Bash-Script" class="headerlink" title="Bash Script"></a>Bash Script</h3><p>Often, I don’t know what to put for this type. After some research in the huge list mentioned earlier, my doubt is finally solved. <strong>It can be <code>shell</code>, <code>bash</code>, <code>sh</code> or <code>zsh</code>.</strong></p><h3 id="diff"><a href="#diff" class="headerlink" title="diff"></a><code>diff</code></h3><p>When I discovered this <code>diff</code> type as one of the language option for Fenced Code Block, I realised this is extremely helpful to highlight what has been changed for not only code but also configuration, especially the latter.</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">some_config = "1"</span><br><span class="line"><span class="deletion">- some_other_config = "2"</span></span><br><span class="line"><span class="addition">+ some_other_config = "3"</span></span><br></pre></td></tr></table></figure><h3 id="File-Path-in-Hexo"><a href="#File-Path-in-Hexo" class="headerlink" title="File Path in Hexo"></a>File Path in Hexo</h3><p>In Hexo, we could add a space followed by the <code>file path</code> after adding language for Fenced Code Block (<strong>Note:</strong> this does not work on GitHub).</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="code">```diff configuration.file</span></span><br><span class="line"><span class="code">some_config = "1"</span></span><br><span class="line"><span class="code">- some_other_config = "2"</span></span><br><span class="line"><span class="code">+ some_other_config = "3"</span></span><br><span class="line"><span class="code">```</span></span><br></pre></td></tr></table></figure><p>Fenced Code Block above will be rendered as:</p><figure class="highlight diff"><figcaption><span>configuration.file</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">some_config = "1"</span><br><span class="line"><span class="deletion">- some_other_config = "2"</span></span><br><span class="line"><span class="addition">+ some_other_config = "3"</span></span><br></pre></td></tr></table></figure><hr><h2 id="Referrence"><a href="#Referrence" class="headerlink" title="Referrence"></a>Referrence</h2><p><a href="https://github.com/github/linguist/blob/master/lib/linguist/languages.yml">GitHub known languages</a></p><p><a href="https://www.markdownguide.org/">Markdown Guide</a></p><p><a href="https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md">Rules for markdownlint extension</a></p>]]></content>
<summary type="html"><h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><blockquote>
<p>Hmm, another article talking about Markdown?</p>
</blockquote>
<p>Well, I am not going through the Markdown syntax one by one in this article, I am pretty sure they are quite easy to master after some practices. But instead, I will talk about some hidden parts (at least to me😅) of the Markdown syntax, especially after using <a href="https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint">markdownlint</a> extension.</p>
<p>If you are looking for a quick Markdown Cheat Sheet, you could refer to <a href="https://www.markdownguide.org/cheat-sheet/">Markdown Guide</a>. In summary, all basic syntax are supported for hexo with next theme (I am not sure whether theme matters, but let’s be precise); for the extended syntax, <code>Table</code>, <code>Fenced Code Block</code>, <code>Definition List</code>, <code>Strikethrough</code> and <code>Task List</code> (not sure the purpose of this in a blog article though) are supported. That’s good enough for writting a good blog article with Markdown, hooray🎉.</p></summary>
<category term="miscellaneous" scheme="https://comilao.github.io/categories/miscellaneous/"/>
<category term="hexo" scheme="https://comilao.github.io/tags/hexo/"/>
<category term="vscode" scheme="https://comilao.github.io/tags/vscode/"/>
<category term="markdown" scheme="https://comilao.github.io/tags/markdown/"/>
</entry>
<entry>
<title>Markdown with VS Code</title>
<link href="https://comilao.github.io/setup/vscode/vscode_markdown/"/>
<id>https://comilao.github.io/setup/vscode/vscode_markdown/</id>
<published>2022-01-24T14:36:27.000Z</published>
<updated>2022-01-29T16:00:00.000Z</updated>
<content type="html"><![CDATA[<h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><p>As I will be writing lots of Markdowns, I spend some time researching VS Code Markdown extensions and creating snippets to enhance the writing experience.</p><span id="more"></span><hr><h2 id="Extensions"><a href="#Extensions" class="headerlink" title="Extensions"></a>Extensions</h2><h3 id="markdownlint"><a href="#markdownlint" class="headerlink" title="markdownlint"></a>markdownlint</h3><p><a href="https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint">markdownlint</a> applies a set of linting rules to Markdown file.</p><p>To exclude certain rules, you can add following configuration to VS Code settings at <code>.vscode/settings.json</code> (This settings file only applies to Workspace level, which I recommend it over User level).</p><p>Below is an example to exclude inline-html from linting:</p><figure class="highlight json"><figcaption><span>vscode/settings.json</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"markdownlint.config"</span>: {</span><br><span class="line"> <span class="comment">// Exclude inline-html from linting</span></span><br><span class="line"> <span class="attr">"MD033"</span>: <span class="literal">false</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="Coloring-Header"><a href="#Coloring-Header" class="headerlink" title="Coloring Header"></a>Coloring Header</h3><p><a href="https://marketplace.visualstudio.com/items?itemName=satokaz.vscode-markdown-header-coloring">Markdown Header Coloring</a> colors Markdown header tags.</p><p>I use a dark theme called <a href="https://ahmadawais.com/shades-of-purple/">Shades of Purple</a> for VS Code. In this theme, the heading syntax is not very prominent, as the author says he prefers the syntax to be as hidden as possible. I like this theme a lot, but my only complaint is this <strong>hidden heading syntax</strong>, hence I find this extension extremely helpful!</p><h3 id="GitHub-Style-Preview"><a href="#GitHub-Style-Preview" class="headerlink" title="GitHub Style Preview"></a>GitHub Style Preview</h3><p><a href="https://marketplace.visualstudio.com/items?itemName=bierner.markdown-preview-github-styles">Markdown Preview GitHub Styling</a> changes the built-in markdown to match GitHub’s styling.</p><hr><h2 id="Snippets"><a href="#Snippets" class="headerlink" title="Snippets"></a>Snippets</h2><blockquote><p>Code snippets are templates that make it easier to enter repeating code patterns, such as loops or conditional-statements.</p></blockquote><p><a href="https://code.visualstudio.com/docs/editor/userdefinedsnippets">From Snippets in VS Code</a>. (You can try <code>for</code> in a JavaScript file with VS Code to learn how to use a snippet.)</p><h3 id="Enable-Quick-Suggestion"><a href="#Enable-Quick-Suggestion" class="headerlink" title="Enable Quick Suggestion"></a>Enable Quick Suggestion</h3><p>Before using snippets in a Markdown file, quick suggestions in VS Code needs to be enabled. From the <a href="https://code.visualstudio.com/docs/editor/intellisense">Intellisense</a> page, it is enabled only for certain languages (Like JavaScript, TypeScript, JSON and etc.). Support for other languages (e.g. Python, Go and etc.) are managed by their corresponding extentions.</p><p>For Markdown, we can enable quick suggestions in VS Code settings (Code -> Preferences -> Settings):</p><ol><li>Once in the settings page, you can decide whether to apply this setting to User or Workspace level by toggle between User and Workspace. (I prefer to keep language specific settings at Workspace level though.)</li><li>Go to the top right corner and look for “Open Settings (JSON)” button and click it.</li><li>Type <code>"[markdown]"</code> and select <code>[markdown]</code> from the quick suggestion popup window (Because the settings file is JSON, so quick suggestion works there 😜).</li></ol><h3 id="Markdown-Snippets"><a href="#Markdown-Snippets" class="headerlink" title="Markdown Snippets"></a>Markdown Snippets</h3><p>Then change the <code>[markdown]</code> settings to:</p><figure class="highlight json"><figcaption><span>settings.json</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"[markdown]"</span>: {</span><br><span class="line"> <span class="attr">"editor.unicodeHighlight.ambiguousCharacters"</span>: <span class="literal">false</span>,</span><br><span class="line"> <span class="attr">"editor.wordWrap"</span>: <span class="string">"on"</span>,</span><br><span class="line"> <span class="attr">"editor.quickSuggestions"</span>: {</span><br><span class="line"> <span class="attr">"other"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="attr">"comments"</span>: <span class="literal">false</span>,</span><br><span class="line"> <span class="attr">"strings"</span>: <span class="literal">false</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>After that we can start adding customized snippets for Markdown in VS Code. Go to User Snippets (Code -> Preferences -> User Snippets) and select <code>markdown.json</code>. Below are snippets I used:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"link"</span>: {</span><br><span class="line"> <span class="attr">"description"</span>: <span class="string">"Insert link"</span>,</span><br><span class="line"> <span class="attr">"prefix"</span>: <span class="string">"lk"</span>,</span><br><span class="line"> <span class="attr">"body"</span>: <span class="string">"[${1:name}](${2:url})"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="attr">"link with clipboard url"</span>: {</span><br><span class="line"> <span class="attr">"description"</span>: <span class="string">"Insert link with url from clipboard"</span>,</span><br><span class="line"> <span class="attr">"prefix"</span>: <span class="string">"lku"</span>,</span><br><span class="line"> <span class="attr">"body"</span>: <span class="string">"[${1:name}]($CLIPBOARD)"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="attr">"link with clipboard text"</span>: {</span><br><span class="line"> <span class="attr">"description"</span>: <span class="string">"Insert link with name from clipboard"</span>,</span><br><span class="line"> <span class="attr">"prefix"</span>: <span class="string">"lkt"</span>,</span><br><span class="line"> <span class="attr">"body"</span>: <span class="string">"[$CLIPBOARD](${1:url})"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="attr">"image with clipboard url"</span>: {</span><br><span class="line"> <span class="attr">"description"</span>: <span class="string">"Insert image with url from clipboard"</span>,</span><br><span class="line"> <span class="attr">"prefix"</span>: <span class="string">"imgu"</span>,</span><br><span class="line"> <span class="attr">"body"</span>: <span class="string">""</span></span><br><span class="line"> },</span><br><span class="line"> <span class="attr">"link with header id"</span>: {</span><br><span class="line"> <span class="comment">// markdown specific for hexo</span></span><br><span class="line"> <span class="attr">"description"</span>: <span class="string">"[hexo]\n \"## Header something\" should be \n \"Header-something\""</span>,</span><br><span class="line"> <span class="attr">"prefix"</span>: <span class="string">"lkh"</span>,</span><br><span class="line"> <span class="attr">"body"</span>: <span class="string">"[${1:name}](#${2:url})"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="attr">"table"</span>: {</span><br><span class="line"> <span class="attr">"description"</span>: <span class="string">"Insert table"</span>,</span><br><span class="line"> <span class="attr">"prefix"</span>: <span class="string">"table"</span>,</span><br><span class="line"> <span class="attr">"body"</span>: [</span><br><span class="line"> <span class="string">"| Header1 | Header2 |"</span>,</span><br><span class="line"> <span class="string">"| --- | --- |"</span>,</span><br><span class="line"> <span class="string">"| content | content |"</span>,</span><br><span class="line"> <span class="string">"| content | content |"</span>,</span><br><span class="line"> ]</span><br><span class="line"> },</span><br><span class="line"> <span class="attr">"more button"</span>: {</span><br><span class="line"> <span class="comment">// markdown specific for hexo, but can be used to put hidden comments in markdown</span></span><br><span class="line"> <span class="attr">"description"</span>: <span class="string">"[hexo]\n \"Read More >>\" button in blog article for hexo next theme"</span>,</span><br><span class="line"> <span class="attr">"prefix"</span>: <span class="string">"more"</span>,</span><br><span class="line"> <span class="attr">"body"</span>: <span class="string">"<!-- more -->"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="attr">"hr line"</span>: {</span><br><span class="line"> <span class="comment">// to obey markdownlint's MD035 - Horizontal rule style</span></span><br><span class="line"> <span class="attr">"description"</span>: <span class="string">"Insert consistent hr"</span>,</span><br><span class="line"> <span class="attr">"prefix"</span>: <span class="string">"hr"</span>,</span><br><span class="line"> <span class="attr">"body"</span>: <span class="string">"---"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="attr">"codeblock with language"</span>: {</span><br><span class="line"> <span class="attr">"description"</span>: <span class="string">"codeblock with frequently used languages"</span>,</span><br><span class="line"> <span class="attr">"prefix"</span>: <span class="string">"block"</span>,</span><br><span class="line"> <span class="attr">"body"</span>: [</span><br><span class="line"> <span class="string">"```${1|python,diff,shell,json|}"</span>,</span><br><span class="line"> <span class="string">"```"</span></span><br><span class="line"> ]</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="Referrence"><a href="#Referrence" class="headerlink" title="Referrence"></a>Referrence</h2><ul><li><p><a href="https://www.deepanseeralan.com/tech/enable-quick-suggestions-for-markdown-in-vscode/">Enable quick suggestions for Markdown in VS Code</a></p></li><li><p>Some Markdown snippets are from <a href="https://github.com/gggwvg/vscode-snippets-markdown">vscode-snippets-markdown</a> (The use of <code>$CLIPBOARD</code> is really clever!)</p></li><li><p><a href="https://www.freecodecamp.org/news/create-your-own-custom-code-snippets/">“Step 6: Create Choices” for custom snippet</a> (I never know snippet placeholder could have choices!)</p></li></ul>]]></content>
<summary type="html"><h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><p>As I will be writing lots of Markdowns, I spend some time researching VS Code Markdown extensions and creating snippets to enhance the writing experience.</p></summary>
<category term="setup" scheme="https://comilao.github.io/categories/setup/"/>
<category term="vscode" scheme="https://comilao.github.io/categories/setup/vscode/"/>
<category term="setup" scheme="https://comilao.github.io/tags/setup/"/>
<category term="vscode" scheme="https://comilao.github.io/tags/vscode/"/>
<category term="vscode extension" scheme="https://comilao.github.io/tags/vscode-extension/"/>
<category term="markdown" scheme="https://comilao.github.io/tags/markdown/"/>
</entry>
<entry>
<title>Hexo Next Theme Customization</title>
<link href="https://comilao.github.io/setup/hexo/hexo_next_customization/"/>
<id>https://comilao.github.io/setup/hexo/hexo_next_customization/</id>
<published>2022-01-21T09:37:30.000Z</published>
<updated>2022-01-29T16:00:00.000Z</updated>
<content type="html"><![CDATA[<h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><p>Please refer to <a href="https://theme-next.js.org/docs/">next theme documentation page</a> for more settings. Settings discussed in this blog post are the one used for this site only.</p><span id="more"></span><h2 id="Change-favicon"><a href="#Change-favicon" class="headerlink" title="Change favicon"></a>Change favicon</h2><p>After changing to <a href="https://theme-next.js.org/">next theme</a>, the Hexo site uses the default next <code>favicon</code>, you could change to your preferred <code>favicon</code> for your blog.</p><p>For me, I choose the reading icon from <a href="https://www.flaticon.com/free-icons/student">here</a> and use <a href="https://realfavicongenerator.net/">Favicon Generator</a> to generate icons and stored them under <code>source/images</code> folder as shown below.</p><!-- TODO try to look for another way to acknowledge --><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── source</span><br><span class="line">│ ├── _posts</span><br><span class="line">│ ├── images</span><br><span class="line">│ ├── apple-touch-icon-reading.png</span><br><span class="line">│ ├── favicon-16x16-reading.png</span><br><span class="line">│ ├── favicon-32x32-reading.png</span><br><span class="line">│ └── logo.svg</span><br><span class="line">│</span><br></pre></td></tr></table></figure><p>Remember to change <code>_config.next.yml</code> as well:</p><figure class="highlight diff"><figcaption><span>_config.next.yml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">favicon:</span><br><span class="line"><span class="deletion">- small: /images/favicon-16x16-next.png</span></span><br><span class="line"><span class="deletion">- medium: /images/favicon-32x32-next.png</span></span><br><span class="line"><span class="deletion">- apple_touch_icon: /images/apple-touch-icon-next.png</span></span><br><span class="line"><span class="addition">+ small: /images/favicon-16x16-reading.png</span></span><br><span class="line"><span class="addition">+ medium: /images/favicon-32x32-reading.png</span></span><br><span class="line"><span class="addition">+ apple_touch_icon: /images/apple-touch-icon-reading.png</span></span><br><span class="line"> safari_pinned_tab: /images/logo.svg</span><br></pre></td></tr></table></figure><h2 id="Display-Categories-and-Tags-Page"><a href="#Display-Categories-and-Tags-Page" class="headerlink" title="Display Categories and Tags Page"></a>Display Categories and Tags Page</h2><p>I prefer to use categories and tags pages for a better organization.</p><p>To make some buttons like <code>Categories</code> and <code>Tags</code> appear in the <code>Menu Settings</code> section, I first change next theme configuration file.</p><figure class="highlight diff"><figcaption><span>_config.next.yml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"># ---------------------------------------------------------------</span><br><span class="line"># Menu Settings</span><br><span class="line"># ---------------------------------------------------------------</span><br><span class="line"></span><br><span class="line"># Usage: `Key: /link/ || icon`</span><br><span class="line"># Key is the name of menu item. If the translation for this item is available, the translated text will be loaded, otherwise the Key name will be used. Key is case-sensitive.</span><br><span class="line"># Value before `||` delimiter is the target link, value after `||` delimiter is the name of Font Awesome icon.</span><br><span class="line"># External url should start with http:// or https://</span><br><span class="line">menu:</span><br><span class="line"><span class="deletion">- #home: / || fa fa-home</span></span><br><span class="line"><span class="addition">+ home: / || fa fa-home</span></span><br><span class="line"> #about: /about/ || fa fa-user</span><br><span class="line"><span class="deletion">- #tags: /tags/ || fa fa-tags</span></span><br><span class="line"><span class="deletion">- #categories: /categories/ || fa fa-th</span></span><br><span class="line"><span class="deletion">- #archives: /archives/ || fa fa-archive</span></span><br><span class="line"><span class="addition">+ tags: /tags/ || fa fa-tags</span></span><br><span class="line"><span class="addition">+ categories: /categories/ || fa fa-th</span></span><br><span class="line"><span class="addition">+ archives: /archives/ || fa fa-archive</span></span><br><span class="line"> #schedule: /schedule/ || fa fa-calendar</span><br><span class="line"> #sitemap: /sitemap.xml || fa fa-sitemap</span><br><span class="line"> #commonweal: /404/ || fa fa-heartbeat</span><br></pre></td></tr></table></figure><p>Besides changing next theme configuration file, <code>source/categories/index.md</code> and <code>source/tags/index.md</code> also need to be created with following contents.</p><figure class="highlight yml"><figcaption><span>source/categories/index.md</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">Categories</span></span><br><span class="line"><span class="attr">date:</span> <span class="number">2022-01-23 18:08:00</span></span><br><span class="line"><span class="attr">type:</span> <span class="string">"categories"</span></span><br><span class="line"><span class="meta">---</span></span><br></pre></td></tr></table></figure><figure class="highlight yml"><figcaption><span>source/tags/index.md</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">Tags</span></span><br><span class="line"><span class="attr">date:</span> <span class="number">2022-01-23 18:08:00</span></span><br><span class="line"><span class="attr">type:</span> <span class="string">"tags"</span></span><br><span class="line"><span class="meta">---</span></span><br></pre></td></tr></table></figure><h2 id="Read-More-Button"><a href="#Read-More-Button" class="headerlink" title="Read More Button"></a>Read More Button</h2><p>By default, I realised the whole post is displayed on the home page, which means lots of scrolling is required to view the next post. By adding this line <code><!-- more --></code> in a markdown file, a <code>Read more >></code> button will be generated to minimize the post height in the home page.</p><p>After adding <code><!-- more --></code> in the markdown files, run following commands:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># generate static files locally</span></span><br><span class="line">hexo g</span><br><span class="line"><span class="comment"># if above command do not work, run clean command before generating static files locally command</span></span><br><span class="line">hexo clean</span><br></pre></td></tr></table></figure><h2 id="Faster-Animation"><a href="#Faster-Animation" class="headerlink" title="Faster Animation"></a>Faster Animation</h2><p>The default next theme’s animation is quite slow, however, I found out changing <code>enable: false</code> under <code>motion</code> section, the sidebar (red box in the screenshot below) with author name and number of posts disappeared completely.</p><img src="https://i.imgur.com/JNpXKIL.png" alt="sidebar of Pisces and Gemini schemes" width="30%" height="30%"><p>After some research online, I decided to go for this <a href="https://github.com/next-theme/hexo-theme-next/issues/138">configuration</a>.</p><ul><li><code>async: true</code> allows all elements to load together</li><li><code>post_block: none</code> allows no css animation to be applied when loading an element</li></ul><figure class="highlight diff"><figcaption><span>_config.next.yml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"># ---------------------------------------------------------------</span><br><span class="line"># Animation Settings</span><br><span class="line"># ---------------------------------------------------------------</span><br><span class="line"></span><br><span class="line"># Use Animate.css to animate everything.</span><br><span class="line"># For more information: https://animate.style</span><br><span class="line">motion:</span><br><span class="line"> enable: true</span><br><span class="line"><span class="deletion">- async: false</span></span><br><span class="line"><span class="addition">+ async: true</span></span><br><span class="line"> transition:</span><br><span class="line"> # All available transition variants: https://theme-next.js.org/animate/</span><br><span class="line"><span class="deletion">- post_block: fadeIn</span></span><br><span class="line"><span class="deletion">- post_header: fadeInDown</span></span><br><span class="line"><span class="deletion">- post_body: fadeInDown</span></span><br><span class="line"><span class="deletion">- coll_header: fadeInLeft</span></span><br><span class="line"><span class="addition">+ post_block: none</span></span><br><span class="line"><span class="addition">+ post_header: none</span></span><br><span class="line"><span class="addition">+ post_body: none</span></span><br><span class="line"><span class="addition">+ coll_header: none</span></span><br><span class="line"> # Only for Pisces | Gemini.</span><br><span class="line"><span class="deletion">- sidebar: fadeInUp</span></span><br><span class="line"><span class="addition">+ sidebar: none</span></span><br></pre></td></tr></table></figure><p>However, the menu area above sidebar (blue box in the screenshot above) still has some css animation effects applied, I am not sure how to change it though, but in general I am quite happy with the loading time now!</p><h2 id="Social-Icons"><a href="#Social-Icons" class="headerlink" title="Social Icons"></a>Social Icons</h2><p>Add a GitHub social icons in the blog.</p><figure class="highlight diff"><figcaption><span>_config.next.yml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># Social Links</span><br><span class="line"># Usage: `Key: permalink || icon`</span><br><span class="line"># Key is the link label showing to end users.</span><br><span class="line"># Value before `||` delimiter is the target permalink, value after `||` delimiter is the name of Font Awesome icon.</span><br><span class="line">social:</span><br><span class="line"><span class="deletion">- GitHub: https://github.com/yourname || fab fa-github</span></span><br><span class="line"><span class="addition">+ GitHub: https://github.com/comilao || fab fa-github</span></span><br></pre></td></tr></table></figure><p>To display social icons only without descriptions.</p><figure class="highlight diff"><figcaption><span>_config.next.yml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">social_icons:</span><br><span class="line"> enable: true</span><br><span class="line"><span class="deletion">- icons_only: false</span></span><br><span class="line"><span class="addition">+ icons_only: true</span></span><br><span class="line"> transition: false</span><br></pre></td></tr></table></figure><h2 id="RSS-Feed"><a href="#RSS-Feed" class="headerlink" title="RSS Feed"></a>RSS Feed</h2><p>Install <a href="https://github.com/hexojs/hexo-generator-feed">hexo-generator-feed</a>:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-generator-feed --save</span><br></pre></td></tr></table></figure><p>Add RSS Feed icon at social icons section:</p><figure class="highlight diff"><figcaption><span>_config.next.yml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">social:</span><br><span class="line"> GitHub: https://github.com/comilao || fab fa-github</span><br><span class="line"><span class="addition">+ RSS: /atom.xml || fa fa-rss</span></span><br></pre></td></tr></table></figure><h2 id="Local-Search"><a href="#Local-Search" class="headerlink" title="Local Search"></a>Local Search</h2><p>Install <a href="https://github.com/next-theme/hexo-generator-searchdb">hexo-generator-searchdb</a>:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-generator-searchdb</span><br></pre></td></tr></table></figure><p>Change settings at:</p><figure class="highlight diff"><figcaption><span>_config.next.yml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># Local Search</span><br><span class="line"># Dependencies: https://github.com/next-theme/hexo-generator-searchdb</span><br><span class="line">local_search:</span><br><span class="line"><span class="deletion">- enable: false</span></span><br><span class="line"><span class="addition">+ enable: true</span></span><br></pre></td></tr></table></figure><p>If some strange icons appeared in the menu area after <code>hexo generate</code> command, remember to do a <code>hexo clean</code> before <code>hexo generate</code>.</p><h2 id="Codeblock-Copy-Button"><a href="#Codeblock-Copy-Button" class="headerlink" title="Codeblock Copy Button"></a>Codeblock Copy Button</h2><p>Enable copy button on codeblock</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> # Add copy button on codeblock</span><br><span class="line"> copy_button:</span><br><span class="line"><span class="deletion">- enable: false</span></span><br><span class="line"><span class="addition">+ enable: true</span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><p>Please refer to <a href="https://theme-next.js.org/docs/">next theme documentation page</a> for more settings. Settings discussed in this blog post are the one used for this site only.</p></summary>
<category term="setup" scheme="https://comilao.github.io/categories/setup/"/>
<category term="hexo" scheme="https://comilao.github.io/categories/setup/hexo/"/>
<category term="setup" scheme="https://comilao.github.io/tags/setup/"/>
<category term="hexo" scheme="https://comilao.github.io/tags/hexo/"/>
<category term="hexo next theme" scheme="https://comilao.github.io/tags/hexo-next-theme/"/>
</entry>
<entry>
<title>Hexo Setup GitHub Pages</title>
<link href="https://comilao.github.io/setup/hexo/hexo_gh_pages/"/>
<id>https://comilao.github.io/setup/hexo/hexo_gh_pages/</id>
<published>2022-01-21T07:46:27.000Z</published>
<updated>2022-01-20T16:00:00.000Z</updated>
<content type="html"><![CDATA[<h2 id="Deploy-to-GitHub-Pages"><a href="#Deploy-to-GitHub-Pages" class="headerlink" title="Deploy to GitHub Pages"></a>Deploy to GitHub Pages</h2><p>Creating a GitHub Pages site is quite simple. With a GitHub account, a <code><github-username>.github.io</code> repository could be created.</p><p>Once GitHub Pages repository has been successfully created, the next job is to generate static files and deploy them to GitHub Pages reposity to host.</p><span id="more"></span><p>Change <code>_config.yml</code>:</p><figure class="highlight diff"><figcaption><span>_config.yml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># Deployment</span><br><span class="line">## Docs: https://hexo.io/docs/one-command-deployment</span><br><span class="line">deploy:</span><br><span class="line"><span class="deletion">- type: git</span></span><br><span class="line"><span class="addition">+ type: git</span></span><br><span class="line"><span class="addition">+ repo: https://github.com/comilao/comilao.github.io.git</span></span><br><span class="line"><span class="addition">+ branch: master</span></span><br></pre></td></tr></table></figure><p>Install plugin <code>hexo-deployer-git</code>:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-deployer-git</span><br></pre></td></tr></table></figure><p>To deploy, run the following commands:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo g -d</span><br></pre></td></tr></table></figure><p>You browser will open and you need to authorize the action in order to deploy generated static files to GitHub Pages repository.</p>]]></content>
<summary type="html"><h2 id="Deploy-to-GitHub-Pages"><a href="#Deploy-to-GitHub-Pages" class="headerlink" title="Deploy to GitHub Pages"></a>Deploy to GitHub Pages</h2><p>Creating a GitHub Pages site is quite simple. With a GitHub account, a <code>&lt;github-username&gt;.github.io</code> repository could be created.</p>
<p>Once GitHub Pages repository has been successfully created, the next job is to generate static files and deploy them to GitHub Pages reposity to host.</p></summary>
<category term="setup" scheme="https://comilao.github.io/categories/setup/"/>
<category term="hexo" scheme="https://comilao.github.io/categories/setup/hexo/"/>
<category term="setup" scheme="https://comilao.github.io/tags/setup/"/>
<category term="hexo" scheme="https://comilao.github.io/tags/hexo/"/>
<category term="github pages" scheme="https://comilao.github.io/tags/github-pages/"/>
</entry>
<entry>
<title>Hexo Setup General</title>
<link href="https://comilao.github.io/setup/hexo/hexo_general/"/>
<id>https://comilao.github.io/setup/hexo/hexo_general/</id>
<published>2022-01-21T00:45:07.000Z</published>
<updated>2022-01-20T16:00:00.000Z</updated>
<content type="html"><![CDATA[<h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><p>As a new year resolution, I would like to be better than last year. In the technical aspect, I think starting a blog might be a good way (provided I could keep this habit). I used hexo before, however, due to issues with organizing blog articles and the ugly defaul theme, I stopped after a few articles. After organizing all my browser bookmarks last week, I got some inspirations on how to organize things, hence I am starting a new hexo blog again. Let’s see how far this time I could go.</p><p>But firstly, I decided to fix some issues I faced before, to keep my interest and form a habbit of good structure with tags and categories.</p><span id="more"></span><hr><h2 id="Requirements"><a href="#Requirements" class="headerlink" title="Requirements"></a>Requirements</h2><p>More could be found on <a href="https://hexo.io/">Hexo website</a>:</p><ul><li>Nodejs</li><li>Git</li></ul><h2 id="Installation"><a href="#Installation" class="headerlink" title="Installation"></a>Installation</h2><p>Install Hexo globally with <code>npm</code> on the machine:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g hexo-cli</span><br></pre></td></tr></table></figure><h2 id="Setup"><a href="#Setup" class="headerlink" title="Setup"></a>Setup</h2><p>Once Hexo is installed, run following commands to initialize Hexo in the target <code><folder></code>.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">hexo init <folder></span><br><span class="line"><span class="built_in">cd</span> <folder></span><br><span class="line">npm install</span><br></pre></td></tr></table></figure><hr><h2 id="Configuration"><a href="#Configuration" class="headerlink" title="Configuration"></a>Configuration</h2><p><strong>Note:</strong> This section contains my preference (Marked with <em>Personally</em>).</p><h3 id="Hexo"><a href="#Hexo" class="headerlink" title="Hexo"></a>Hexo</h3><p>Site settings could be modified in <code>_config.yml</code>.</p><p><em>Personally</em>, I feel <code>categories</code> in the <code>permalink</code> can help with better organization.</p><figure class="highlight diff"><figcaption><span>_config.yml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># URL</span><br><span class="line">...</span><br><span class="line"><span class="deletion">- permalink: :year/:month/:day/:title/</span></span><br><span class="line"><span class="addition">+ permalink: :category/:name/</span></span><br></pre></td></tr></table></figure><p>Difference between <code>:title</code> and <code>:name</code>:</p><p><code>:title</code> is filename relative to <code>source/_posts</code> folder, whereas <code>:name</code> is just filename.</p><p>For example, content below at the start of the markdown file with different <code>permalink</code> setting generates different <code>permalink</code>. (Note the extra 2022 for <code>:title</code> setting)</p><figure class="highlight yaml"><figcaption><span>source/_posts/2022/hello-world.md</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">title:</span> <span class="string">Hello</span> <span class="string">World</span></span><br><span class="line"><span class="attr">date:</span> <span class="number">2022-01-21 17:01:34</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>Setting</th><th>Result</th></tr></thead><tbody><tr><td><code>:year/:month/:day/:title/</code></td><td>2022/01/21/2022/hello-world/</td></tr><tr><td><code>:year/:month/:day/:name/</code></td><td>2022/01/21/hello-world/</td></tr></tbody></table><h3 id="Post-Layout"><a href="#Post-Layout" class="headerlink" title="Post Layout"></a>Post Layout</h3><p><em>Personally</em>, I prefer to add <code>updated</code> and <code>categories</code> in the default post layout, this two extra properties can help with better organization. I also like to have a <strong>Preface</strong> section with a <strong>more</strong> button to provide a quick summary of the blog post without occupying lots of space by showing the whole article.</p><figure class="highlight diff"><figcaption><span>./scaffolds/post.md</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">---</span></span><br><span class="line">title: {{ title }}</span><br><span class="line">date: {{ date }}</span><br><span class="line"><span class="addition">+ updated:</span></span><br><span class="line"><span class="addition">+ categories:</span></span><br><span class="line">tags:</span><br><span class="line"><span class="comment">---</span></span><br><span class="line"></span><br><span class="line">## Preface</span><br><span class="line"></span><br><span class="line"><!-- more --></span><br></pre></td></tr></table></figure><h3 id="Theme"><a href="#Theme" class="headerlink" title="Theme"></a>Theme</h3><p><em>Personally</em>, the default theme is not very aesthetic appealing to me. I decided to change to <a href="https://github.com/next-theme/hexo-theme-next">Next</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> <hexo_folder></span><br><span class="line">npm install hexo-theme-next</span><br><span class="line"><span class="comment"># optional: remove landscape theme node package and configuration file</span></span><br><span class="line">npm uninstall hexo-theme-landscape</span><br><span class="line">rm _config.landscape.yml</span><br></pre></td></tr></table></figure><p>Change theme to next:</p><figure class="highlight diff"><figcaption><span>_config.yml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># Extensions</span><br><span class="line">## Plugins: https://hexo.io/plugins/</span><br><span class="line">## Themes: https://hexo.io/themes/</span><br><span class="line"><span class="deletion">- theme: landscape</span></span><br><span class="line"><span class="addition">+ theme: next</span></span><br></pre></td></tr></table></figure><p>Customize next theme (Copy theme config file to <code>hexo_folder</code> root directory):</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># copy command for installation with npm</span></span><br><span class="line">cp node_modules/hexo-theme-next/_config.yml _config.next.yml</span><br></pre></td></tr></table></figure><p>My preferred Scheme is Gemini.</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"># ---------------------------------------------------------------</span><br><span class="line"># Scheme Settings</span><br><span class="line"># ---------------------------------------------------------------</span><br><span class="line"></span><br><span class="line"># Schemes</span><br><span class="line"><span class="deletion">- scheme: Muse</span></span><br><span class="line"><span class="addition">+ #scheme: Muse</span></span><br><span class="line">#scheme: Mist</span><br><span class="line">#scheme: Pisces</span><br><span class="line"><span class="deletion">- #scheme: Gemini</span></span><br><span class="line"><span class="addition">+ scheme: Gemini</span></span><br></pre></td></tr></table></figure><hr><h2 id="Frequently-Used-Commands"><a href="#Frequently-Used-Commands" class="headerlink" title="Frequently Used Commands"></a>Frequently Used Commands</h2><h3 id="new"><a href="#new" class="headerlink" title="new"></a>new</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">hexo new [layout] <title> -p [path_to_article_file]</span><br><span class="line"><span class="comment"># short form</span></span><br><span class="line">hexo n [layout] <title> -p [path_to_article_file]</span><br></pre></td></tr></table></figure><p>Creates a new article.</p><p>If no <code>layout</code> is specified, <code>default_layout</code> from <code>_config.yml</code> is used. (That is why I changed <code>scaffolds/post.md</code> described in <code>Configuration</code> sections.)</p><p>If <code>title</code> contains space inside, surround it with quotation marks.</p><p><em>Personally</em>, I prefer to specify the path to article file when creating a new article, hence I added this <code>-p [path_to_article_file]</code> to the command.</p><p><strong>Note:</strong><br>| <code>path_to_article_file</code> parameter | Actual file path created |<br>| — | ———– |<br>| <code>setup</code> | <code>setup.md</code> |<br>| <code>setup/hexo_1.md</code> | <code>setup/hexo_1.md</code> |<br>| <code>setup/</code> | <code>setup/.md</code> |</p><h3 id="server"><a href="#server" class="headerlink" title="server"></a>server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">hexo server</span><br><span class="line"><span class="comment"># short form</span></span><br><span class="line">hexo s</span><br><span class="line"><span class="comment"># serving static files</span></span><br><span class="line">hexo s -s</span><br></pre></td></tr></table></figure><p>Starts a local server at <code>http://localhost:4000</code> by default.</p><h3 id="generate"><a href="#generate" class="headerlink" title="generate"></a>generate</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">hexo generate</span><br><span class="line"><span class="comment"># short form</span></span><br><span class="line">hexo g</span><br><span class="line"><span class="comment"># deploy after generation</span></span><br><span class="line">hexo g -d</span><br></pre></td></tr></table></figure><p>Generates static files locally.</p><h3 id="clean"><a href="#clean" class="headerlink" title="clean"></a>clean</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo clean</span><br></pre></td></tr></table></figure><p>Cleans the cache file (db.json) and generated files (public).</p><p>If changing a certain setting does not take effect in the generated static files, running this command and generate static files again could solve the problem. (The favorite restart/reset solves the issue🤣)</p>]]></content>
<summary type="html"><h2 id="Preface"><a href="#Preface" class="headerlink" title="Preface"></a>Preface</h2><p>As a new year resolution, I would like to be better than last year. In the technical aspect, I think starting a blog might be a good way (provided I could keep this habit). I used hexo before, however, due to issues with organizing blog articles and the ugly defaul theme, I stopped after a few articles. After organizing all my browser bookmarks last week, I got some inspirations on how to organize things, hence I am starting a new hexo blog again. Let’s see how far this time I could go.</p>
<p>But firstly, I decided to fix some issues I faced before, to keep my interest and form a habbit of good structure with tags and categories.</p></summary>
<category term="setup" scheme="https://comilao.github.io/categories/setup/"/>
<category term="hexo" scheme="https://comilao.github.io/categories/setup/hexo/"/>
<category term="setup" scheme="https://comilao.github.io/tags/setup/"/>
<category term="hexo" scheme="https://comilao.github.io/tags/hexo/"/>
</entry>
</feed>