Rapid Refactoring With Vim

栏目: IT技术 · 发布时间: 4年前

内容简介:Last weekend, I was tasked with refactoring the 96 unit tests onHere's a small sample of what had to be done (note the lines prefixed with the arrow):had to be converted to:

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, 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 callinstead, 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 recordedmacro 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 . 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.


以上所述就是小编给大家介绍的《Rapid Refactoring With Vim》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深入理解计算机系统(原书第3版)

深入理解计算机系统(原书第3版)

Randal E.Bryant、David O'Hallaron / 龚奕利、贺莲 / 机械工业出版社 / 2016-11 / 139.00元

和第2版相比,本版内容上*大的变化是,从以IA32和x86-64为基础转变为完全以x86-64为基础。主要更新如下: 基于x86-64,大量地重写代码,首次介绍对处理浮点数据的程序的机器级支持。 处理器体系结构修改为支持64位字和操作的设计。 引入更多的功能单元和更复杂的控制逻辑,使基于程序数据流表示的程序性能模型预测更加可靠。 扩充关于用GOT和PLT创建与位置无关代码的......一起来看看 《深入理解计算机系统(原书第3版)》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具