Reputation: 78528
In Python code, I frequently run into import statements like this:
from foo import ppp, zzz, abc
Is there any Vim trick, like :sort
for lines, to sort to this:
from foo import abc, ppp, zzz
Upvotes: 12
Views: 3571
Reputation: 5636
Select the comma-separated text in visual mode, :, and run this command:
'<,'>!tr ',' '\n' | sort -f | paste -sd ','
🎩-tip this comment
Upvotes: 1
Reputation: 61
I came here looking for a fast way to sort comma separated lists, in general, e.g.
relationships = {
'project', 'freelancer', 'task', 'managers', 'team'
}
My habit was to search/replace spaces with newlines and invoke shell sort but that's such a pain.
I ended up finding Chris Toomey's sort-motion
plugin, which is just the ticket: https://github.com/christoomey/vim-sort-motion. Highly recommended.
Upvotes: 3
Reputation: 778
Why not try vim-isort ? https://github.com/fisadev/vim-isort
I use that and vim-yapf-format for beautify the code :) https://github.com/pignacio/vim-yapf-format
Upvotes: 1
Reputation: 9137
Alternatively, you can do the following steps:
Move the words you want to sort to the next line:
from foo import ppp, zzz, abc
Add a comma at the end of the words list:
from foo import ppp, zzz, abc,
Select the word list for example with Shift-v. Now hit : and then enter !xargs -n1 | sort | xargs
. It should look like this:
:'<,'>!xargs -n1 | sort | xargs
Hit Enter.
from foo import abc, ppp, zzz,
Now remove the trailing comma and merge the word list back to the original line (for example with Shift-j).
from foo import abc, ppp, zzz
There are Vim plugins, which might be useful to you:
Upvotes: 4
Reputation: 32966
Yep, there is:
%s/import\s*\zs.*/\=join(sort(split(submatch(0), '\s*,\s*')),', ')
The key elements are:
To answer the comment, if you want to apply the substitution on a visual selection, it becomes:
'<,'>s/\%V.*\%V\@!/\=join(sort(split(submatch(0), '\s*,\s*')), ', ')
The new key elements are this time:
:h /\%V
that says the next character matched shall belong to the visual selection:h /\@!
that I use, in order to express (combined with \%V
), that the next character shall not belong to the visual selection. That next character isn't kept in the matched expression.BTW, we can also use s
and i_CTRL-R_=
interactively, or put it in a mapping (here triggered on µ
):
:xnoremap µ s<c-r>=join(sort(split(@", '\s*,\s*')), ', ')<cr><esc>
Upvotes: 15