diff options
Diffstat (limited to 'docs/index.xml')
-rw-r--r-- | docs/index.xml | 207 |
1 files changed, 207 insertions, 0 deletions
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 | ||
17 | tests on | ||
18 | <a href="https://github.com/ruma/ruma-events/pull/70">ruma-events</a> | ||
19 | to use strictly typed json objects using <code>serde_json::json!</code> | ||
20 | instead of raw strings. It was rather painless thanks to | ||
21 | vim :)</p> | ||
22 | |||
23 | <p>Here's a small sample of what had to be done (note the lines | ||
24 | prefixed 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::<Action>(r#"{"set_tweak": "highlight"}"#), | ||
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::<Action>(json!({"set_tweak": "highlight"})), | ||
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 | ||
53 | a simple find and replace operation, done to all the files | ||
54 | containing tests. Luckily, modules (and therefore files) | ||
55 | containing 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 | |||
61 | vim $(grep -l 'cfg\(test\)' ./**/*.rs) | ||
62 | |||
63 | # expands to something like: | ||
64 | vim push_rules.rs room/member.rs key/verification/lib.rs | ||
65 | </code></pre> | ||
66 | |||
67 | <p>Starting vim with more than one file at the shell prompt | ||
68 | populates the arglist. Hit <code>:args</code> to see the list of | ||
69 | files currently ready to edit. The square [brackets] | ||
70 | indicate the current file. Navigate through the arglist | ||
71 | with <code>:next</code> and <code>:prev</code>. I use tpope'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's left to do is the find and replace, for which we | ||
76 | will be using vim's <code>argdo</code>, applying a substitution to | ||
77 | every file in the arglist:</p> | ||
78 | |||
79 | <pre><code>:argdo s/from_str/from_value/g | ||
80 | </code></pre> | ||
81 | |||
82 | <h2 id="The%20quickfix%20list">The quickfix list</h2> | ||
83 | |||
84 | <p>Next up, replacing <code>r#" ... "#</code> with <code>json!( ... )</code>. I | ||
85 | couldn't search and replace that trivially, so I went with a | ||
86 | macro call <sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup> instead, starting with the cursor on | ||
87 | ‘r’, represented by the caret, in my attempt to breakdown | ||
88 | the process:</p> | ||
89 | |||
90 | <pre><code>BUFFER: r#" ... "#; | ||
91 | ^ | ||
92 | |||
93 | ACTION: vllsjson!( | ||
94 | |||
95 | BUFFER json!( ... "#; | ||
96 | ^ | ||
97 | |||
98 | ACTION: <esc>$F# | ||
99 | |||
100 | BUFFER: json!( ... "#; | ||
101 | ^ | ||
102 | |||
103 | ACTION: vhs)<esc> | ||
104 | |||
105 | BUFFER: json!( ... ); | ||
106 | </code></pre> | ||
107 | |||
108 | <p>Here's the recorded <sup id="fnref3"><a href="#fn3" rel="footnote">3</a></sup> macro in all its glory: | ||
109 | <code>vllsjson!(<esc>$F#vhs)<esc></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 | ||
113 | more than a few occurrences of raw strings that had to stay | ||
114 | raw strings. Enter, the quickfix list.</p> | ||
115 | |||
116 | <p>The idea behind the quickfix list is to jump from one | ||
117 | position in a file to another (maybe in a different file), | ||
118 | much like how the arglist lets you jump from one file to | ||
119 | another.</p> | ||
120 | |||
121 | <p>One of the easiest ways to populate this list with a bunch | ||
122 | of 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 'r#' ./**/*.rs | ||
129 | </code></pre> | ||
130 | |||
131 | <p>Like <code>:next</code> and <code>:prev</code>, you can navigate the quickfix list | ||
132 | with <code>:cnext</code> and <code>:cprev</code>. Every time you move up or down | ||
133 | the list, vim indicates your index:</p> | ||
134 | |||
135 | <pre><code>(1 of 131): r#"{"set_tweak": "highlight"}"#; | ||
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 | ||
145 | some 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 | ||
150 | inside the <code>json!</code> macro. All you have to do is pass a | ||
151 | visual selection through a pretty json printer. Select the | ||
152 | range to be formatted in visual mode, and hit <code>:</code>, you will | ||
153 | notice the command line displaying what seems to be | ||
154 | gibberish:</p> | ||
155 | |||
156 | <pre><code>:'<,'> | ||
157 | </code></pre> | ||
158 | |||
159 | <p><code>'<</code> and <code>'></code> are <em>marks</em> <sup id="fnref4"><a href="#fn4" rel="footnote">4</a></sup>. More | ||
160 | specifically, they are marks that vim sets automatically | ||
161 | every time you make a visual selection, denoting the start | ||
162 | and 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 | :'a,'b mark 'a' to mark 'b' | ||
171 | </code></pre> | ||
172 | |||
173 | <p>Most <code>:</code> commands can be prefixed by ranges. <code>:help | ||
174 | usr_10.txt</code> for more on that.</p> | ||
175 | |||
176 | <p>Alright, lets pass json through <code>python -m json.tool</code>, a | ||
177 | json formatter that accepts <code>stdin</code> (note the use of <code>!</code> to | ||
178 | make use of an external program):</p> | ||
179 | |||
180 | <pre><code>:'<,'>!python -m json.tool | ||
181 | </code></pre> | ||
182 | |||
183 | <p>Unfortunately that didn't quite work for me because the | ||
184 | range included some non-json text as well, a mix of regex | ||
185 | and 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 | ||
188 | sort 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://github.com/tpope/vim-unimpaired</a> | ||
196 | It also handles various other mappings, <code>]q</code> and <code>[q</code> to | ||
197 | navigate the quickfix list for example <a href="#fnref1" rev="footnote">↩</a></p> | ||
198 | </li> | ||
199 | |||
200 | <li id="fn2"> | ||
201 | <p><code>:help recording</code> <a href="#fnref2" rev="footnote">↩</a></p> | ||
202 | </li> | ||
203 | |||
204 | <li id="fn3"> | ||
205 | <p>When I'm recording a macro, I prefer starting out by | ||
206 | storing it in register <code>q</code>, and then copying it over to | ||
207 | another register if it works as intended. I think of <code>qq</code> as | ||
208 | ‘quick record’. <a href="#fnref3" rev="footnote">↩</a></p> | ||
209 | </li> | ||
210 | |||
211 | <li id="fn4"> | ||
212 | <p><code>:help mark-motions</code> <a href="#fnref4" rev="footnote">↩</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 |
17 | experience <sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>, and common sense. This post aims to debunk some | 224 | experience <sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>, and common sense. This post aims to debunk some |