Hot answers tagged

11

Vim's sort allows you to either skip {pattern}, or only consider it (with the r flag). A regular expression for the last comma-delimited column is easy to formulate: Skip everything until and including the last comma in a line: :sort/.*,/ For any other column, I would use the r flag, and skip N (here: 2) previous columns via \zs: :sort/\([^,]*,\)\{2}\zs[^,...


10

If you can use the rev command, you could reverse each line, sort and reverse again, using external commands in a pipe: %!rev | sort | rev This can be done entirely in Vimscript, but it's way more verbose: function! RTLSort() range " reversing function for use with map() function! Rev(k, str) " the first argument from map() is an index, so ...


10

The easy way: join the lines in the logical blocks before sorting. In detail: mark the lines join the indented lines to the lines above: :'<,'>s/\n /^A/ mark the lines again: gv sort them: :'<,'>sort mark the lines one more time: gv split the lines back and restore indentation: :'<,'>s/^A/\r /g ^A above is the character Ctrl-A (ASCII SOH)...


9

I think your best hope is the vis.vim plugin. This plugin provides a command B which allows to apply a command to a block. Here after installing the plugin, you'd select your block and then use: :'<,'>B !sort Note that the command can be anything, so instead of !sort you could do a lot of other processing on the block like saving it to another file (...


9

You could define a "sort lines" operator like this: function! s:SortLinesOpFunc(...) '[,']sort endfunction nnoremap <silent> \s :<C-u>set operatorfunc=<SID>SortLinesOpFunc<CR>g@ \sip will sort the paragraph under the cursor and, in general, \s{motion} will sort the lines moved over by {motion}, inclusively. See :help :map-...


6

In :<from>,<to>command, both <from> and <to> are relative to the current line. What you want is to make <to> relative to <from>. For this you need :help :;: :/foo/;,/bar/command where the cursor is moved to /foo/ first, which becomes the current line. :/<table class=.bar\_.\{-}\zs<tr/;,/table>/sort! n /.\{-}&...


6

Peter Rincker's SortGroup is the go-to script for this kind of work. https://gist.github.com/PeterRincker/582ea9be24a69e6dd8e237eb877b8978 Somewhat differently to vim's :sort, it takes a pattern which is supposed to match the text declaring lines as the start of a group. For example, :SortGroup /^\DeclareAcronym{/ will sort all the DeclareAcronym ...


5

You can capture output with execute() function and then pump it through sort(). The whole command could be then: command! -bang -nargs=1 -complete=command Sorted \ echo join(sort(split(execute(<q-mods> . ' ' . <q-args>), "\n"), \ {s1, s2 -> <bang>(s1 ># s2) - <bang>(s1 <# s2)}), "\n") Now you can do :Sorted ...


5

You can create a simple normal mode mapping: nnoremap <key> :'{,'}sort<CR> usage from normal mode: <key> or a more flexible visual mode mapping: xnoremap <key> :sort<CR> usage from normal mode: vip<key>


5

You can use the built-in sort utility: :sort Or pipe the buffer to an external Unix command: :%!sort For more info and options see :help :sort and man sort.


5

If you don't care about removing the first occurrence (leaving the last one), you can use the following global command: g/^\(.*\)\n\_.*\(^\1$\)/d Decomposing: g/ /d " the global command will delete matched lines ^\(.*\) " Match anything from start of the line (create a group) \n " Match ...


4

Vanilla Vim: Via Expression Register And now a solution for vanilla vim: Position cursor on list ciW (removes unsorted list and puts it into register ") <C-r>=join(sort([<C-r>"]), ',')<CR> Done. I think it is actually not that bad. An even more useful variant would be <C-r>=join(sort(split(expand(@"), ',')), ',')<CR> You ...


4

Idea: Let's join the n number of lines under case to a single line. Follow the process for all cases. Then, use sort to sort the cases. Then, cut those lines back and indent them. Steps: 1) Join n lines following case by typing this. (in your case, n is 3) :g/case / normal! 3gJ 2) Select all such cases using visual mode. Press v ot V to select all cases....


4

Try to add the negative offset -1 to the second line specifier in the range passed to the first substitution command: v :g/^function /,/^}/- s/\n/@@@ :sort /^function / :%s/@@@/\r/g Otherwise, the newline at the end of your first function is replaced with @@@, which wrongly merges the first line of the second function with the last line ...


4

There is no direct functionality for that. (At least non I know of.) Assuming that none of the field short, long and extra contains any line-breaks: First join the lines into a single line. g/^\\DeclareAcronym/,/}}$/join This selects the lines from \Declare to a line that ends with }} and joins those line into a single line. Then sort And finally ...


3

Vim's :sort command can take an optional regex to indicate where to start sorting. From :help :sort: When /{pattern}/ is specified and there is no [r] flag the text matched with {pattern} is skipped, so that you sort on what comes after the match. So this should be enough to sort lines, considering the text coming after the underscore: :sort /_/ The ...


3

Add space between pattern, cmd: g /\v\{/ +1,/\v}/-1 sort ^------------------separation between pattern and command It's a good habit to leave space between pattern and cmd if your cmd takes a range. +1,/\v}/-1 Is a range start from next line until previous line of /\v/. Check :h :range If you have doubts. This range is used for cmd, not for global....


3

:sort i - sorts case-insensitive.


3

Visually select your lines, then run: " join the comments and the related command *g/^\s*#/,/^\s*[^# ]/-s/\n/\="\x01" " sort the lines *sort " split back the lines *s/\%x01/\r/g To operate on the whole buffer rather than the visual selection, replace the * range with %. Note that – in Vim – the comment leader is ", not #; ...


3

I read a little bit more, and there's a function in vimscript called sort() which can receive a function to compare both items. Here's the help page: sort({list} [, {func} [, {dict}]]) sort() E702 Sort the items in {list} in-place. Returns {list}. If you want a list to remain unmodified make a copy first: ...


3

Plugin sort-motion.vim IMO the most convenient method to achieve this is to use a plugin or a self-written vim function linked to a mapping. Both need a customized vim and are obviously not available in vanilla vim. For example, the plugin sort-motion.vim provides a flexible, very convenient solution for your question. Position the cursor anywhere on the ...


3

If your list is already sorted with :sort n, you can move the done D items to the bottom of the list with a global command: :g/^D/m$ This works through the file from top to bottom, moving each line that starts with a D. Because the D lines are already sorted when you run the command, they remain sorted after it. If you want to perform both steps in a ...


3

Try adding this to your .vimrc: nnoremap <leader>td :sort n<CR>:sort n /[D]/<CR> Then in Normal mode, you can type \td (assuming you haven't changed the default leader key to something else) to sort your to-do list.


3

Normaly, I would use :%! sort | uniq -c | sort -nr but this is a shell depended answer. Using only Vim language or ex-commands in Vim is a little bit more difficult and it is very nicely described on wikia in Word frequency statistics for a file. Inspired by that article it is possible to replicate the output of :%! sort | uniq -c | sort -nr with :%s/^\+...


3

The sort pattern is skipped, so you could use sort /.\{-}\ze\u/ or sort r /\u\+/ (the r should cause it sort on the matching parts.) Importantly, any lines not matching are kept in order, but separated. I recognize these are similar to what you tried (with \u instead of [A-Z]). For some reason, it actually made a difference for me. That is, using [A-Z] ...


3

Commands such as :sort /[^A-Z]*/ to skip non-uppercase letters should typically work, except when 'ignorecase' is set, which makes that pattern case-insensitive and will skip characters other than any letters, be them uppercase or lowercase. From the comments, it looks like you do have 'ignorecase' enabled. You might have the pattern /[^A-Z]*/ work correctly ...


2

You could use external commands to do that. Take for example, giving that the buffer has only the content you share the following commands: %!awk -F ',' '{print length($1) "|" $0}' %!sort -nr %norm df| would result in this contents: "Be(C<sub>5</sub>H<sub>7</sub>O<sub>2</sub>)<sub>2</sub>","Be ...


2

The standard trick for doing this is to convert your blocks into single lines not by removing the linebreaks, but instead by replacing them with something you can find again easily after the sort. e.g. Replace all linebreaks that don't follow a } with LINEBREAK: :%s/}\@<!\n/LINEBREAK Sort: :sort Split the blocks into multiple lines again: :%s/...


2

Here is a different approach. :filter let will only look for matching variable names, so you can re-implement it using filter() function and sort the resulting dict and output all matches afterwards. This is using the new method functionality of Vim 8.1 and a lambda expression. for val in sort(keys((copy(g:)->filter({k -> k =~# 'python'}))))|echo ...


2

At first make every digit zero: :%s/\vprivate const .* = \zs\d*\ze;/0/g Then goto the first line with gg Then start recording. Just press q twice, i.e. qq. The first q will start the recording and the second q will define in which register (:reg q) the recording will be stored. Goto the digit before ; by pressing t; Yank the integer with yiw Go one line ...


Only top voted, non community-wiki answers of a minimum length are eligible