问题
The question's title might sound a little vague, so I'll explain the situation here more clearly.
I have these lines of code in a file which I want to align with respect to the character =.
const service = require('./service');
const baseService = require('./baseService');
const config = require('../config');
const Promise = require('bluebird');
const errors = require('../errors');
I want the above lines to somehow look like this
const service = require('./service');
const baseService = require('./baseService');
const config = require('../config');
const Promise = require('bluebird');
const errors = require('../errors');
I want all the = characters to lie in the same column and shift the after-coming code accordingly. What can I do to achieve this task?
A plugin capable of doing this would be nice, but it'd be great if I could do this without the aid of any plugin. That way I'd also learn something.
回答1:
Using GNU tools
:%!column -t -s= -o=
% ............. current file
! ............. use external command
-t ............. use tabs
-s ............. input separator
-o ............. output separator
Instead of whole file it can be a range of lines 1,5 or you can select a paragraph with vip
I ended up creating a function called AlignText that uses column command to solve this issue:
" Align text by a chosen char
" https://stackoverflow.com/questions/57093175/
" https://vi.stackexchange.com/a/2412/7339
if !exists('*AlignText')
function! AlignText(param) range
execute a:firstline . ',' . a:lastline . '!column -t -s' . a:param . ' -o' . a:param
endfunction
endif
command! -range=% -nargs=1 Align <line1>,<line2>call AlignText(<q-args>)
" :Align =
" :8,$ Align =
If you wnat to test this function before put it into your vimrc, copy the code to your clipboard and then try this:
:@+
Now you can use something like this:
:15,22Align /
:Align ,
I by any change you want to use the function call instead of the command one, don't forget to pass the range and put the argument between quotes.
A slitly different version that accepts nor arguments and uses just "column -t"
" https://stackoverflow.com/questions/57093175/
" https://vi.stackexchange.com/a/2412/7339
function! AlignText(...) range
if a:0 < 1
execute a:firstline . ',' . a:lastline . '!column -t'
else
execute a:firstline . ',' . a:lastline . '!column -t -s' . a:1 . ' -o' . a:1
endif
endfunction
command! -range=% -nargs=? Align <line1>,<line2>call AlignText(<f-args>)
回答2:
there are plugins can do this kind of alignment. E.g.
Align or easy-align. I have been using Align for a long time, for your requirement, I just select those lines and do <leader>t=
https://github.com/vim-scripts/Align
https://github.com/junegunn/vim-easy-align
You can of course code by yourself, you find out the max length before the =, then you know how many spaces you should insert between partBefore and =. (the diff) on each line.
回答3:
(NOTE: Originally answered at the Vi and Vim Stack Exchange.)
If you're in a pinch and want to get the expressions aligned, without having to install and learn any plug-ins, here is a quick way to do it.
- Select the lines on a visual selection. For example, if this is your whole buffer, you could use
ggVG, but if these lines are in the middle of a file, just select appropriately. PerhapsV4j? - Insert enough whitespace before the
=, which you can do with:normal f=9i. (Note the "space" at the end.) This will add 9 spaces before each=in the lines of the visual selection. If 9 is not enough, add more (like 99 or 999, as much as you want.) Note that when you type:with the visual selection, Vim will automatically insert the range, so the actual command is:'<,'>normal f=9i, but you don't need to type those characters. - Move to the column where you want the
=s to be flushed to. In this case, line 2 has the longest variable name, so move to two spaces after the end of that name, which is where the=s should be at the end. If this is the whole buffer, you could use2G2e2lto get there. - Staying on that same column, move to the first line of the block. In this case, you're moving from line 2 to line 1, so
kis enough. - Start visual-block selection, pressing
Ctrl-V. - Move to the last line of the block. If this is the whole buffer, you could use
G, if this is the middle of a file, you could use4jto go four lines down, etc. - (Optional) Use
$to select until the end of the line, on every line of the visual block selection. UPDATE: This step is actually not necessary here, since<will work correctly even if you don't select lines to the end. Using$is important when using e.g.Ato append to the end of all lines though. - Now you can use the
<command to shift the lines left, but until they hit the left of the visual block. Each<will shift them by one'shiftwidth'only, so you're likely to need more than one. So, to be sure, use9<(or99<, or999<, if you added tons of spaces in step 2.)
Voilà!
This is a pretty cool technique and it can be helpful when you need more flexibility than plug-ins can afford you. It's a good one to learn and keep on your Vim toolbox.
来源:https://stackoverflow.com/questions/57093175/indent-a-block-of-code-on-the-basis-of-a-single-character