From 709f56c17a8563ef9388f85ce9faeadb1e1d07f4 Mon Sep 17 00:00:00 2001 From: Akshay Date: Wed, 1 Apr 2020 11:58:47 +0530 Subject: new post --- docs/posts/rapid_refactoring_with_vim/index.html | 261 +++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 docs/posts/rapid_refactoring_with_vim/index.html (limited to 'docs/posts/rapid_refactoring_with_vim/index.html') 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 @@ + + + + + + + + + + + + + + Rapid Refactoring With Vim · peppe.rs + +
+
+ ⟵ Back + View Raw +
+
+ 01/04 — 2020 +
+ + 79.12 + + cm +   + + 5.4 + + min +
+
+ + Rapid Refactoring With Vim + +
+

Last weekend, I was tasked with refactoring the 96 unit +tests on +ruma-events +to use strictly typed json objects using serde_json::json! +instead of raw strings. It was rather painless thanks to +vim :)

+ +

Here's a small sample of what had to be done (note the lines +prefixed with the arrow):

+ +
→ use serde_json::{from_str};
+  
+  #[test]
+  fn deserialize() {
+    assert_eq!(
+→       from_str::<Action>(r#"{"set_tweak": "highlight"}"#),
+        Action::SetTweak(Tweak::Highlight { value: true })
+        );
+  }
+
+ +

had to be converted to:

+ +
→ use serde_json::{from_value};
+  
+  #[test]
+  fn deserialize() {
+    assert_eq!(
+→       from_value::<Action>(json!({"set_tweak": "highlight"})),
+        Action::SetTweak(Tweak::Highlight { value: true })
+        );
+  }
+
+ +

The arglist

+ +

For the initial pass, I decided to handle imports, this was +a simple find and replace operation, done to all the files +containing tests. Luckily, modules (and therefore files) +containing tests in Rust are annotated with the +#[cfg(test)] attribute. I opened all such files:

+ +
# `grep -l pattern files` lists all the files
+#  matching the pattern
+
+vim $(grep -l 'cfg\(test\)' ./**/*.rs)
+
+# expands to something like:
+vim push_rules.rs room/member.rs key/verification/lib.rs
+
+ +

Starting vim with more than one file at the shell prompt +populates the arglist. Hit :args to see the list of +files currently ready to edit. The square [brackets] +indicate the current file. Navigate through the arglist +with :next and :prev. I use tpope's vim-unimpaired +1, which adds ]a and [a, mapped to :next and +:prev.

+ +

All that's left to do is the find and replace, for which we +will be using vim's argdo, applying a substitution to +every file in the arglist:

+ +
:argdo s/from_str/from_value/g
+
+ +

The quickfix list

+ +

Next up, replacing r#" ... "# with json!( ... ). I +couldn't search and replace that trivially, so I went with a +macro call 2 instead, starting with the cursor on +‘r’, represented by the caret, in my attempt to breakdown +the process:

+ +
BUFFER:    r#" ... "#;
+           ^
+
+ACTION:    vllsjson!(
+
+BUFFER     json!( ... "#;
+                ^
+
+ACTION:    <esc>$F#
+
+BUFFER:    json!( ... "#;
+                       ^
+
+ACTION:    vhs)<esc>
+
+BUFFER:    json!( ... );
+
+ +

Here's the recorded 3 macro in all its glory: +vllsjson!(<esc>$F#vhs)<esc>.

+ +

Great! So now we just go ahead, find every occurrence of +r# and apply the macro right? Unfortunately, there were +more than a few occurrences of raw strings that had to stay +raw strings. Enter, the quickfix list.

+ +

The idea behind the quickfix list is to jump from one +position in a file to another (maybe in a different file), +much like how the arglist lets you jump from one file to +another.

+ +

One of the easiest ways to populate this list with a bunch +of positions is to use vimgrep:

+ +
# basic usage
+:vimgrep pattern files
+
+# search for raw strings
+:vimgrep 'r#' ./**/*.rs
+
+ +

Like :next and :prev, you can navigate the quickfix list +with :cnext and :cprev. Every time you move up or down +the list, vim indicates your index:

+ +
(1 of 131): r#"{"set_tweak": "highlight"}"#;
+
+ +

And just like argdo, you can cdo to apply commands to +every match in the quickfix list:

+ +
:cdo norm! @q
+
+ +

But, I had to manually pick out matches, and it involved +some button mashing.

+ +

External Filtering

+ +

Some code reviews later, I was asked to format all the json +inside the json! macro. All you have to do is pass a +visual selection through a pretty json printer. Select the +range to be formatted in visual mode, and hit :, you will +notice the command line displaying what seems to be +gibberish:

+ +
:'<,'>
+
+ +

'< and '> are marks 4. More +specifically, they are marks that vim sets automatically +every time you make a visual selection, denoting the start +and end of the selection.

+ +

A range is one or more line specifiers separated by a ,:

+ +
:1,7       lines 1 through 7
+:32        just line 32
+:.         the current line
+:.,$       the current line to the last line
+:'a,'b     mark 'a' to mark 'b'
+
+ +

Most : commands can be prefixed by ranges. :help +usr_10.txt for more on that.

+ +

Alright, lets pass json through python -m json.tool, a +json formatter that accepts stdin (note the use of ! to +make use of an external program):

+ +
:'<,'>!python -m json.tool
+
+ +

Unfortunately that didn't quite work for me because the +range included some non-json text as well, a mix of regex +and macros helped fix that. I think you get the drift.

+ +

Another fun filter I use from time to time is :!sort, to +sort css attributes, or :!uniq to remove repeated imports.

+ +
+
+
    + +
  1. +

    https://github.com/tpope/vim-unimpaired +It also handles various other mappings, ]q and [q to +navigate the quickfix list for example 

    +
  2. + +
  3. +

    :help recording 

    +
  4. + +
  5. +

    When I'm recording a macro, I prefer starting out by +storing it in register q, and then copying it over to +another register if it works as intended. I think of qq as +‘quick record’. 

    +
  6. + +
  7. +

    :help mark-motions 

    +
  8. + +
+
+ +
+ +
+ Hi. Subscribe +

I'm Akshay, I go by nerd or nerdypepper on the internet.

+

+ I am a compsci undergrad, Rust programmer and an enthusiastic Vimmer. + I write open-source stuff to pass time. I also design fonts: scientifica, curie. + Things I find cool usually end up here. +

+

Get in touch at nerd@irc.rizon.net or nerdypepper@chat.freenode.net.

+
+ + ⟵ Back + View Raw +
+
+ + -- cgit v1.2.3