开发者

What is the best way to refactor a Ruby ‘if’ statement into one-line shorthand form in Vim?

开发者 https://www.devze.com 2023-04-05 06:09 出处:网络
I have the following Ruby code: if some_cond && another foo_bar end and I want to change it to: foo_bar if some_cond && another

I have the following Ruby code:

if some_cond && another
  foo_bar
end

and I want to change it to:

foo_bar if some_cond && another

What are the most idiomatic ways to do tha开发者_StackOverflow社区t in Vim?


Assuming that the cursor is located at the if-line prior to refactoring (not necessarily at the beginning of that line), I would use the following sequence of Normal-mode commands:

ddjVpkJ<<

or this chain of Ex commands:

:m+|-j|<|+d

Here the if-line is first moved down one line by the :move + command. The :move command cuts a given range of lines (the current line, if not specified) and pastes it below the line addressed by the argument. The + address is a shorthand for .+1 referring to the next line (see :help {address}).

Second, the line containing the body of the conditional statement is joined with the just moved if-line. The :join command concatenates a given range of lines into a single line. The - range is a shortened form of the .-1 address referring to the line just above the cursor (see :help {address}).

Third, the newly joined line is unindented by one shiftwidth using the :< command.

Finally, the remaining end-line, which can now be addressed as +, is removed by the :delete command.


I see few (probably non-optimal) solutions:

  1. cursor in first character in first line:

    • D - remove if condition but leave cursor in same position (don't delete line)
    • J - join next line to current
    • A <Space> <ESC> - append space and exit to Normal mode
    • p - paste if condition
    • and then remove remaining end with jdd
  2. cursor in first character in first line, as previously:

    • j - move to next line
    • dd - remove this line
    • k - move back to if condition
    • P - paste removed line before actual line, cursor should be placed to pasted line
    • J - join next line to current
    • == or << - unindent current line
    • and then remove remaining end with jdd
  3. another solution:

    • j - move to second line
    • JD - join line with next, remove what was joined
    • dd - remove current line
    • k - step to previous line
    • PJ<< - paste, join and unshift

It's probably not optimal, but I do it without thinking, because most of this commands are in my muscle memory (you don't think how to move around you, how to yank/delete and paste most of the time, and joining line is also helpful to remember).

If you have virtualedit enabled in config, instead of A <Space> <Esc> you can $ <Space>, but I find $ harder to use than A followed by Ctrl-[ (it's simmilar to ESC).

As an advice: if you use some upper letter commands, try to chain them if it's possible, so you only need to keep Shift pressed and then execute some commands, instead of mixing upper and lower letter commands and pressing two keys at a time (upper letter is 2 key press, one is Shift). Once I found combo helpful for restarting server in console Ctrl+cpj, which sends Ctrl+c, Ctrl+p (previous command) and Ctrl+j (Enter key) with single Ctrl press. Since then I try to find simmilar time-saving combination in Vim too mostly with Shift, as Ctrl is not much used in Vim.


Yet another way:

ddpkJjdd
  • ddp swap the two lines
  • kJ move up and join the lines
  • == re-indent the line
  • jdd move down and delete the last line


There are probably 30 ways to do this.

Here is one, assuming you are starting from the end of the word end in normal mode:

dd (delete last line)
"aD (delete and copy foo_bar to buffer a)
dd (delete now-empty line 2)
"aP (paste from buffer a before caret)
aSpaceEsc (insert space and return to normal mode)

Again, "properly" rarely applies in Vim because there are so many ways to accomplish something. This is so small a change that even re-typing foo_bar could be justifiable.

0

精彩评论

暂无评论...
验证码 换一张
取 消