├── .gitignore ├── License.md ├── README.md ├── autoload └── sort_motion.vim ├── doc └── sort_motion.txt └── plugin └── sort_motion.vim /.gitignore: -------------------------------------------------------------------------------- 1 | tags 2 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Chris Toomey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sort Motion.vim 2 | =============== 3 | 4 | This plugin provides the ability to sort in Vim using text objects and 5 | motions. Sorting lines and argument lists manually can be a hassle, and thus 6 | most write it off as a waste of effort, but when its as easy as anything else 7 | in Vim, it becomes a viable option. 8 | 9 | `sort-motion` has three different sorting modes: 10 | 11 | - Linewise: sort a sequence of lines (require statements, gem lists, etc) 12 | - Character: sort a comma separated list (argument lists, attribute lists, etc) 13 | - Visual (linewise or normal): provided for continuity, similar to linewise 14 | - Block Visual: By default behaves the same as the other visual modes. 15 | Optionally, you can provide a specific sort command which you might use to 16 | sort by a column (example: `Vissort`) 17 | 18 | Installation 19 | ------------ 20 | 21 | Using [Vundle][]: 22 | 23 | ``` vim 24 | " add this line to your ~/.vimrc 25 | Bundle 'christoomey/vim-sort-motion' 26 | ``` 27 | 28 | then run `:BundleInstall` from within Vim. 29 | 30 | [Vundle]: https://github.com/gmarik/Vundle.vim 31 | 32 | Usage 33 | ----- 34 | 35 | ### Linewise 36 | 37 | The primary interface to this plugin is via the `gs` mapping, for sorting 38 | based on a text object or motion. To use the mapping, type `gs` followed by a 39 | motion, ie `2j` to sort down two lines. 40 | 41 | Examples: 42 | 43 | - `gs2j` => Sort down two lines (current + 2 below) 44 | - `gsip` => Sort the current paragraph 45 | - `gsii` => Sort the current indentation level (requires [text-obj-indent plugin][]) 46 | 47 | [text-obj-indent plugin]: https://github.com/kana/vim-textobj-indent 48 | 49 | ### Character 50 | 51 | In addition, if the text object is within a line then `sort-motion` will 52 | attempt to sort the text as a comma separated list. 53 | 54 | Examples: 55 | 56 | `gsi(` => Sort within parenthesis. `(b, c, a)` would become `(a, b, c)` 57 | 58 | ### Visual 59 | 60 | For continuity, `sort-motion` also defines a visual mode mapping for `gs`. 61 | This behaves as a linewise sort over the lines defined by the visual selection. 62 | 63 | You can also (optionally) specify a blockwise command to use for block 64 | selections (example: `Vissort`). 65 | 66 | Configuration 67 | ------------- 68 | 69 | ### sort_motion_flags 70 | 71 | If you'd like to pass any options to `sort` 72 | you can set `g:sort_motion_flags`. For example you could use: 73 | 74 | ```vim 75 | let g:sort_motion_flags = 'ui' 76 | ``` 77 | 78 | To make all sorts case insensitive and remove duplicates. 79 | 80 | *Note*: this only applies to linewise sorting (including visual), but does 81 | not apply to the character based sorting of comma separated lists. 82 | 83 | ### sort_motion_visual_block_command 84 | 85 | If you'd like to specify a specific command to use for blockwise selections you 86 | can set it here. This is useful if for example you want to use `Vissort` so that 87 | you can sort by a column. 88 | 89 | ```vim 90 | let g:sort_motion_visual_block_command = 'Vissort' 91 | ``` 92 | 93 | By default the command used is `sort`. 94 | 95 | NOTE: To use `Vissort` you will need to install this plugin. 96 | -------------------------------------------------------------------------------- /autoload/sort_motion.vim: -------------------------------------------------------------------------------- 1 | " autoload/sort_motion.vim 2 | 3 | if exists('g:autoloaded_sort_motion') 4 | finish 5 | endif 6 | let g:autoloaded_sort_motion = 1 7 | 8 | let s:sort_motion_flags = get(g:, 'sort_motion_flags', '') 9 | 10 | function! sort_motion#sort_motion(mode) abort 11 | let l:sort_motion_visual_block_command = 12 | \ get(g:,'sort_motion_visual_block_command', 'sort') 13 | 14 | if a:mode == 'line' 15 | execute "'[,']sort " . s:sort_motion_flags 16 | elseif a:mode == 'char' 17 | execute "normal! `[v`]y" 18 | let startpos = match(@@, '\v\i') 19 | let parts = split(@@, '\v\i+') 20 | if startpos > 0 21 | let prefix = parts[0] 22 | let delimiter = parts[1] 23 | let suffix = parts[-1] 24 | else 25 | let prefix = '' 26 | let delimiter = parts[0] 27 | let suffix = '' 28 | endif 29 | if prefix == delimiter 30 | let prefix = '' 31 | endif 32 | if suffix == delimiter 33 | let suffix = '' 34 | endif 35 | let sortstart = strlen(prefix) 36 | let sortend = strlen(@@) - sortstart - strlen(suffix) 37 | let sortables = strpart(@@, sortstart, sortend) 38 | let sorted = join(sort(split(sortables, '\V' . escape(delimiter, '\'))), delimiter) 39 | execute "normal! v`]c" . prefix . sorted . suffix 40 | execute "normal! `[" 41 | elseif a:mode == 'V' 42 | execute "'<,'>sort " . s:sort_motion_flags 43 | elseif a:mode ==# '' 44 | execute "'<,'>".l:sort_motion_visual_block_command.' '.s:sort_motion_flags 45 | endif 46 | endfunction 47 | 48 | function! sort_motion#sort_lines() abort 49 | let beginning = line('.') 50 | let end = v:count1 + beginning - 1 51 | execute beginning . ',' . end . 'sort ' . s:sort_motion_flags 52 | endfunction 53 | -------------------------------------------------------------------------------- /doc/sort_motion.txt: -------------------------------------------------------------------------------- 1 | *sort_motion.txt* Sort using text objects and motions. 2 | 3 | ============================================================================== 4 | Descriptions and default values:~ 5 | 6 | *'g:sort_motion'* 7 | Mapping for text object sorting: > 8 | let g:sort_motion = 'gs' 9 | < 10 | 11 | *'g:sort_motion_lines'* 12 | Mapping for linewise sorting: > 13 | let g:sort_motion_lines = 'gss' 14 | < 15 | 16 | *'g:sort_motion_visual'* 17 | Mapping for sorting in |Visual| mode: > 18 | let g:sort_motion_visual = 'gs' 19 | < 20 | ============================================================================== 21 | -------------------------------------------------------------------------------- /plugin/sort_motion.vim: -------------------------------------------------------------------------------- 1 | " sort-motion.vim - Sort based on linewise motions 2 | " Maintainer: Chris Toomey 3 | " Version: 0.1 4 | " Source: http://github.com/christoomey/vim-sort-motion 5 | 6 | if exists('g:loaded_sort_motion') || &cp || v:version < 700 7 | finish 8 | endif 9 | let g:loaded_sort_motion = 1 10 | 11 | nnoremap SortMotion 12 | \ :set opfunc=sort_motion#sort_motiong@ 13 | xnoremap SortMotionVisual 14 | \ :call sort_motion#sort_motion(visualmode()) 15 | nnoremap SortLines 16 | \ :call sort_motion#sort_lines() 17 | 18 | if !hasmapto('SortMotion', 'n') && maparg('gs', 'n') ==# '' 19 | nmap gs SortMotion 20 | endif 21 | if !hasmapto('SortMotionVisual', 'x') && maparg('gs', 'x') ==# '' 22 | xmap gs SortMotionVisual 23 | endif 24 | if !hasmapto('SortLines', 'n') && maparg('gss', 'n') ==# '' 25 | nmap gss SortLines 26 | endif 27 | --------------------------------------------------------------------------------