aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2020-04-01 07:28:47 +0100
committerAkshay <[email protected]>2020-04-01 07:28:47 +0100
commit709f56c17a8563ef9388f85ce9faeadb1e1d07f4 (patch)
tree770fd350319226919788a52bc9ae1bf1ea314ce6
parent465046279325b09bb8ab76c0f111b34dfe498591 (diff)
new post
-rw-r--r--docs/index.html17
-rw-r--r--docs/index.xml207
-rw-r--r--docs/posts/rapid_refactoring_with_vim/index.html261
3 files changed, 485 insertions, 0 deletions
diff --git a/docs/index.html b/docs/index.html
index 0ad7403..881a7e2 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -32,6 +32,23 @@
32 <tr> 32 <tr>
33 <td class=table-post> 33 <td class=table-post>
34 <div class="date"> 34 <div class="date">
35 01/04 — 2020
36 </div>
37 <a href="/posts/rapid_refactoring_with_vim" class="post-link">
38 <span class="post-link">Rapid Refactoring With Vim</span>
39 </a>
40 </td>
41 <td class=table-stats>
42 <span class="stats-number">
43 5.4
44 </span>
45 <span class=stats-unit>min</span>
46 </td>
47 </tr>
48
49 <tr>
50 <td class=table-post>
51 <div class="date">
35 17/03 — 2020 52 17/03 — 2020
36 </div> 53 </div>
37 <a href="/posts/font_size_fallacies" class="post-link"> 54 <a href="/posts/font_size_fallacies" class="post-link">
diff --git a/docs/index.xml b/docs/index.xml
index 57b7984..5f472fa 100644
--- a/docs/index.xml
+++ b/docs/index.xml
@@ -12,6 +12,213 @@
12 <language>en-us</language> 12 <language>en-us</language>
13 <copyright>Creative Commons BY-NC-SA 4.0</copyright> 13 <copyright>Creative Commons BY-NC-SA 4.0</copyright>
14 <item> 14 <item>
15<title>Rapid Refactoring With Vim</title>
16<description><p>Last weekend, I was tasked with refactoring the 96 unit
17tests on
18<a href="https://github.com/ruma/ruma-events/pull/70">ruma-events</a>
19to use strictly typed json objects using <code>serde_json::json!</code>
20instead of raw strings. It was rather painless thanks to
21vim :)</p>
22
23<p>Here&#39;s a small sample of what had to be done (note the lines
24prefixed with the arrow):</p>
25
26<pre><code>→ use serde_json::{from_str};
27
28 #[test]
29 fn deserialize() {
30 assert_eq!(
31→ from_str::&#60;Action&#62;(r#&#34;{&#34;set_tweak&#34;: &#34;highlight&#34;}&#34;#),
32 Action::SetTweak(Tweak::Highlight { value: true })
33 );
34 }
35</code></pre>
36
37<p>had to be converted to:</p>
38
39<pre><code>→ use serde_json::{from_value};
40
41 #[test]
42 fn deserialize() {
43 assert_eq!(
44→ from_value::&#60;Action&#62;(json!({&#34;set_tweak&#34;: &#34;highlight&#34;})),
45 Action::SetTweak(Tweak::Highlight { value: true })
46 );
47 }
48</code></pre>
49
50<h2 id="The%20arglist">The arglist</h2>
51
52<p>For the initial pass, I decided to handle imports, this was
53a simple find and replace operation, done to all the files
54containing tests. Luckily, modules (and therefore files)
55containing tests in Rust are annotated with the
56<code>#[cfg(test)]</code> attribute. I opened all such files:</p>
57
58<pre><code># `grep -l pattern files` lists all the files
59# matching the pattern
60
61vim $(grep -l &#39;cfg\(test\)&#39; .&#47;**&#47;*.rs)
62
63# expands to something like:
64vim push_rules.rs room&#47;member.rs key&#47;verification&#47;lib.rs
65</code></pre>
66
67<p>Starting vim with more than one file at the shell prompt
68populates the arglist. Hit <code>:args</code> to see the list of
69files currently ready to edit. The square [brackets]
70indicate the current file. Navigate through the arglist
71with <code>:next</code> and <code>:prev</code>. I use tpope&#39;s vim-unimpaired
72<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>, which adds <code>]a</code> and <code>[a</code>, mapped to <code>:next</code> and
73<code>:prev</code>.</p>
74
75<p>All that&#39;s left to do is the find and replace, for which we
76will be using vim&#39;s <code>argdo</code>, applying a substitution to
77every file in the arglist:</p>
78
79<pre><code>:argdo s&#47;from_str&#47;from_value&#47;g
80</code></pre>
81
82<h2 id="The%20quickfix%20list">The quickfix list</h2>
83
84<p>Next up, replacing <code>r#&#34; ... &#34;#</code> with <code>json!( ... )</code>. I
85couldn&#39;t search and replace that trivially, so I went with a
86macro call <sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup> instead, starting with the cursor on
87&#8216;r&#8217;, represented by the caret, in my attempt to breakdown
88the process:</p>
89
90<pre><code>BUFFER: r#&#34; ... &#34;#;
91 ^
92
93ACTION: vllsjson!(
94
95BUFFER json!( ... &#34;#;
96 ^
97
98ACTION: &#60;esc&#62;$F#
99
100BUFFER: json!( ... &#34;#;
101 ^
102
103ACTION: vhs)&#60;esc&#62;
104
105BUFFER: json!( ... );
106</code></pre>
107
108<p>Here&#39;s the recorded <sup id="fnref3"><a href="#fn3" rel="footnote">3</a></sup> macro in all its glory:
109<code>vllsjson!(&#60;esc&#62;$F#vhs)&#60;esc&#62;</code>. </p>
110
111<p>Great! So now we just go ahead, find every occurrence of
112<code>r#</code> and apply the macro right? Unfortunately, there were
113more than a few occurrences of raw strings that had to stay
114raw strings. Enter, the quickfix list.</p>
115
116<p>The idea behind the quickfix list is to jump from one
117position in a file to another (maybe in a different file),
118much like how the arglist lets you jump from one file to
119another.</p>
120
121<p>One of the easiest ways to populate this list with a bunch
122of positions is to use <code>vimgrep</code>:</p>
123
124<pre><code># basic usage
125:vimgrep pattern files
126
127# search for raw strings
128:vimgrep &#39;r#&#39; .&#47;**&#47;*.rs
129</code></pre>
130
131<p>Like <code>:next</code> and <code>:prev</code>, you can navigate the quickfix list
132with <code>:cnext</code> and <code>:cprev</code>. Every time you move up or down
133the list, vim indicates your index:</p>
134
135<pre><code>(1 of 131): r#&#34;{&#34;set_tweak&#34;: &#34;highlight&#34;}&#34;#;
136</code></pre>
137
138<p>And just like <code>argdo</code>, you can <code>cdo</code> to apply commands to
139<em>every</em> match in the quickfix list:</p>
140
141<pre><code>:cdo norm! @q
142</code></pre>
143
144<p>But, I had to manually pick out matches, and it involved
145some button mashing.</p>
146
147<h2 id="External%20Filtering">External Filtering</h2>
148
149<p>Some code reviews later, I was asked to format all the json
150inside the <code>json!</code> macro. All you have to do is pass a
151visual selection through a pretty json printer. Select the
152range to be formatted in visual mode, and hit <code>:</code>, you will
153notice the command line displaying what seems to be
154gibberish:</p>
155
156<pre><code>:&#39;&#60;,&#39;&#62;
157</code></pre>
158
159<p><code>&#39;&#60;</code> and <code>&#39;&#62;</code> are <em>marks</em> <sup id="fnref4"><a href="#fn4" rel="footnote">4</a></sup>. More
160specifically, they are marks that vim sets automatically
161every time you make a visual selection, denoting the start
162and end of the selection.</p>
163
164<p>A range is one or more line specifiers separated by a <code>,</code>:</p>
165
166<pre><code>:1,7 lines 1 through 7
167:32 just line 32
168:. the current line
169:.,$ the current line to the last line
170:&#39;a,&#39;b mark &#39;a&#39; to mark &#39;b&#39;
171</code></pre>
172
173<p>Most <code>:</code> commands can be prefixed by ranges. <code>:help
174usr_10.txt</code> for more on that.</p>
175
176<p>Alright, lets pass json through <code>python -m json.tool</code>, a
177json formatter that accepts <code>stdin</code> (note the use of <code>!</code> to
178make use of an external program):</p>
179
180<pre><code>:&#39;&#60;,&#39;&#62;!python -m json.tool
181</code></pre>
182
183<p>Unfortunately that didn&#39;t quite work for me because the
184range included some non-json text as well, a mix of regex
185and macros helped fix that. I think you get the drift.</p>
186
187<p>Another fun filter I use from time to time is <code>:!sort</code>, to
188sort css attributes, or <code>:!uniq</code> to remove repeated imports.</p>
189
190<div class="footnotes">
191<hr/>
192<ol>
193
194<li id="fn1">
195<p><a href="https://github.com/tpope/vim-unimpaired">https:&#47;&#47;github.com&#47;tpope&#47;vim-unimpaired</a>
196It also handles various other mappings, <code>]q</code> and <code>[q</code> to
197navigate the quickfix list for example&#160;<a href="#fnref1" rev="footnote">&#8617;</a></p>
198</li>
199
200<li id="fn2">
201<p><code>:help recording</code>&#160;<a href="#fnref2" rev="footnote">&#8617;</a></p>
202</li>
203
204<li id="fn3">
205<p>When I&#39;m recording a macro, I prefer starting out by
206storing it in register <code>q</code>, and then copying it over to
207another register if it works as intended. I think of <code>qq</code> as
208&#8216;quick record&#8217;.&#160;<a href="#fnref3" rev="footnote">&#8617;</a></p>
209</li>
210
211<li id="fn4">
212<p><code>:help mark-motions</code>&#160;<a href="#fnref4" rev="footnote">&#8617;</a></p>
213</li>
214
215</ol>
216</div></description>
217<link>https://peppe.rs/posts/rapid_refactoring_with_vim/</link>
218<pubDate>Wed, 01 Apr 2020 06:25:00 +0000</pubDate>
219<guid>https://peppe.rs/posts/rapid_refactoring_with_vim/</guid>
220</item>
221<item>
15<title>Font Size Fallacies</title> 222<title>Font Size Fallacies</title>
16<description><p>I am not an expert with fonts, but I do have some 223<description><p>I am not an expert with fonts, but I do have some
17experience <sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>, and common sense. This post aims to debunk some 224experience <sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>, and common sense. This post aims to debunk some
diff --git a/docs/posts/rapid_refactoring_with_vim/index.html b/docs/posts/rapid_refactoring_with_vim/index.html
new file mode 100644
index 0000000..4e33a31
--- /dev/null
+++ b/docs/posts/rapid_refactoring_with_vim/index.html
@@ -0,0 +1,261 @@
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <link rel="stylesheet" href="/style.css">
5 <meta charset="UTF-8">
6 <meta name="viewport" content="initial-scale=1">
7 <meta content="#ffffff" name="theme-color">
8 <meta name="HandheldFriendly" content="true">
9 <meta property="og:title" content="Rapid Refactoring With Vim">
10 <meta property="og:type" content="website">
11 <meta property="og:description" content="a static site {for, by, about} me ">
12 <meta property="og:url" content="https://peppe.rs">
13 <link rel="icon" type="image/x-icon" href="/favicon.png">
14 <title>Rapid Refactoring With Vim · peppe.rs</title>
15 <body>
16 <div class="posts">
17 <div class="post">
18 <a href="/" class="post-end-link">⟵ Back</a>
19 <a class="stats post-end-link" href="https://raw.githubusercontent.com/nerdypepper/site/master/posts/rapid_refactoring_with_vim.md
20">View Raw</a>
21 <div class="separator"></div>
22 <div class="date">
23 01/04 — 2020
24 <div class="stats">
25 <span class="stats-number">
26 79.12
27 </span>
28 <span class="stats-unit">cm</span>
29 &nbsp
30 <span class="stats-number">
31 5.4
32 </span>
33 <span class="stats-unit">min</span>
34 </div>
35 </div>
36 <span class="post-title">
37 Rapid Refactoring With Vim
38 </span>
39 <div class="post-text">
40 <p>Last weekend, I was tasked with refactoring the 96 unit
41tests on
42<a href="https://github.com/ruma/ruma-events/pull/70">ruma-events</a>
43to use strictly typed json objects using <code>serde_json::json!</code>
44instead of raw strings. It was rather painless thanks to
45vim :)</p>
46
47<p>Here&#39;s a small sample of what had to be done (note the lines
48prefixed with the arrow):</p>
49
50<pre><code>→ use serde_json::{from_str};
51
52 #[test]
53 fn deserialize() {
54 assert_eq!(
55→ from_str::&#60;Action&#62;(r#&#34;{&#34;set_tweak&#34;: &#34;highlight&#34;}&#34;#),
56 Action::SetTweak(Tweak::Highlight { value: true })
57 );
58 }
59</code></pre>
60
61<p>had to be converted to:</p>
62
63<pre><code>→ use serde_json::{from_value};
64
65 #[test]
66 fn deserialize() {
67 assert_eq!(
68→ from_value::&#60;Action&#62;(json!({&#34;set_tweak&#34;: &#34;highlight&#34;})),
69 Action::SetTweak(Tweak::Highlight { value: true })
70 );
71 }
72</code></pre>
73
74<h2 id="The%20arglist">The arglist</h2>
75
76<p>For the initial pass, I decided to handle imports, this was
77a simple find and replace operation, done to all the files
78containing tests. Luckily, modules (and therefore files)
79containing tests in Rust are annotated with the
80<code>#[cfg(test)]</code> attribute. I opened all such files:</p>
81
82<pre><code># `grep -l pattern files` lists all the files
83# matching the pattern
84
85vim $(grep -l &#39;cfg\(test\)&#39; .&#47;**&#47;*.rs)
86
87# expands to something like:
88vim push_rules.rs room&#47;member.rs key&#47;verification&#47;lib.rs
89</code></pre>
90
91<p>Starting vim with more than one file at the shell prompt
92populates the arglist. Hit <code>:args</code> to see the list of
93files currently ready to edit. The square [brackets]
94indicate the current file. Navigate through the arglist
95with <code>:next</code> and <code>:prev</code>. I use tpope&#39;s vim-unimpaired
96<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>, which adds <code>]a</code> and <code>[a</code>, mapped to <code>:next</code> and
97<code>:prev</code>.</p>
98
99<p>All that&#39;s left to do is the find and replace, for which we
100will be using vim&#39;s <code>argdo</code>, applying a substitution to
101every file in the arglist:</p>
102
103<pre><code>:argdo s&#47;from_str&#47;from_value&#47;g
104</code></pre>
105
106<h2 id="The%20quickfix%20list">The quickfix list</h2>
107
108<p>Next up, replacing <code>r#&#34; ... &#34;#</code> with <code>json!( ... )</code>. I
109couldn&#39;t search and replace that trivially, so I went with a
110macro call <sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup> instead, starting with the cursor on
111&#8216;r&#8217;, represented by the caret, in my attempt to breakdown
112the process:</p>
113
114<pre><code>BUFFER: r#&#34; ... &#34;#;
115 ^
116
117ACTION: vllsjson!(
118
119BUFFER json!( ... &#34;#;
120 ^
121
122ACTION: &#60;esc&#62;$F#
123
124BUFFER: json!( ... &#34;#;
125 ^
126
127ACTION: vhs)&#60;esc&#62;
128
129BUFFER: json!( ... );
130</code></pre>
131
132<p>Here&#39;s the recorded <sup id="fnref3"><a href="#fn3" rel="footnote">3</a></sup> macro in all its glory:
133<code>vllsjson!(&#60;esc&#62;$F#vhs)&#60;esc&#62;</code>. </p>
134
135<p>Great! So now we just go ahead, find every occurrence of
136<code>r#</code> and apply the macro right? Unfortunately, there were
137more than a few occurrences of raw strings that had to stay
138raw strings. Enter, the quickfix list.</p>
139
140<p>The idea behind the quickfix list is to jump from one
141position in a file to another (maybe in a different file),
142much like how the arglist lets you jump from one file to
143another.</p>
144
145<p>One of the easiest ways to populate this list with a bunch
146of positions is to use <code>vimgrep</code>:</p>
147
148<pre><code># basic usage
149:vimgrep pattern files
150
151# search for raw strings
152:vimgrep &#39;r#&#39; .&#47;**&#47;*.rs
153</code></pre>
154
155<p>Like <code>:next</code> and <code>:prev</code>, you can navigate the quickfix list
156with <code>:cnext</code> and <code>:cprev</code>. Every time you move up or down
157the list, vim indicates your index:</p>
158
159<pre><code>(1 of 131): r#&#34;{&#34;set_tweak&#34;: &#34;highlight&#34;}&#34;#;
160</code></pre>
161
162<p>And just like <code>argdo</code>, you can <code>cdo</code> to apply commands to
163<em>every</em> match in the quickfix list:</p>
164
165<pre><code>:cdo norm! @q
166</code></pre>
167
168<p>But, I had to manually pick out matches, and it involved
169some button mashing.</p>
170
171<h2 id="External%20Filtering">External Filtering</h2>
172
173<p>Some code reviews later, I was asked to format all the json
174inside the <code>json!</code> macro. All you have to do is pass a
175visual selection through a pretty json printer. Select the
176range to be formatted in visual mode, and hit <code>:</code>, you will
177notice the command line displaying what seems to be
178gibberish:</p>
179
180<pre><code>:&#39;&#60;,&#39;&#62;
181</code></pre>
182
183<p><code>&#39;&#60;</code> and <code>&#39;&#62;</code> are <em>marks</em> <sup id="fnref4"><a href="#fn4" rel="footnote">4</a></sup>. More
184specifically, they are marks that vim sets automatically
185every time you make a visual selection, denoting the start
186and end of the selection.</p>
187
188<p>A range is one or more line specifiers separated by a <code>,</code>:</p>
189
190<pre><code>:1,7 lines 1 through 7
191:32 just line 32
192:. the current line
193:.,$ the current line to the last line
194:&#39;a,&#39;b mark &#39;a&#39; to mark &#39;b&#39;
195</code></pre>
196
197<p>Most <code>:</code> commands can be prefixed by ranges. <code>:help
198usr_10.txt</code> for more on that.</p>
199
200<p>Alright, lets pass json through <code>python -m json.tool</code>, a
201json formatter that accepts <code>stdin</code> (note the use of <code>!</code> to
202make use of an external program):</p>
203
204<pre><code>:&#39;&#60;,&#39;&#62;!python -m json.tool
205</code></pre>
206
207<p>Unfortunately that didn&#39;t quite work for me because the
208range included some non-json text as well, a mix of regex
209and macros helped fix that. I think you get the drift.</p>
210
211<p>Another fun filter I use from time to time is <code>:!sort</code>, to
212sort css attributes, or <code>:!uniq</code> to remove repeated imports.</p>
213
214<div class="footnotes">
215<hr/>
216<ol>
217
218<li id="fn1">
219<p><a href="https://github.com/tpope/vim-unimpaired">https:&#47;&#47;github.com&#47;tpope&#47;vim-unimpaired</a>
220It also handles various other mappings, <code>]q</code> and <code>[q</code> to
221navigate the quickfix list for example&#160;<a href="#fnref1" rev="footnote">&#8617;</a></p>
222</li>
223
224<li id="fn2">
225<p><code>:help recording</code>&#160;<a href="#fnref2" rev="footnote">&#8617;</a></p>
226</li>
227
228<li id="fn3">
229<p>When I&#39;m recording a macro, I prefer starting out by
230storing it in register <code>q</code>, and then copying it over to
231another register if it works as intended. I think of <code>qq</code> as
232&#8216;quick record&#8217;.&#160;<a href="#fnref3" rev="footnote">&#8617;</a></p>
233</li>
234
235<li id="fn4">
236<p><code>:help mark-motions</code>&#160;<a href="#fnref4" rev="footnote">&#8617;</a></p>
237</li>
238
239</ol>
240</div>
241
242 </div>
243
244 <div class=intro>
245 Hi. <a href=https://peppe.rs/index.xml class=feed-button>Subscribe</a>
246 <p>I'm Akshay, I go by nerd or nerdypepper on the internet.</p>
247 <p>
248 I am a compsci undergrad, Rust programmer and an enthusiastic Vimmer.
249 I write open-source stuff to pass time. I also design fonts: scientifica, curie.
250 Things I find cool usually end up here.
251 </p>
252 <p>Get in touch at [email protected] or [email protected].</p>
253 </div>
254
255 <a href="/" class="post-end-link">⟵ Back</a>
256 <a class="stats post-end-link" href="https://raw.githubusercontent.com/nerdypepper/site/master/posts/rapid_refactoring_with_vim.md
257">View Raw</a>
258 </div>
259 </div>
260 </body>
261</html>