"============================================================================== " Function to sort lines based on a particular column. " Credit must go to the original author Robert Webb. " Modifications by : Aziz Mohammed(aziz@freeshell.org) " Available online at http://aziz.freeshell.org/vim " ----------------------------------------------------------------------------- " Version : 1.0 " Last update : Sat Aug 05 2000 " ----------------------------------------------------------------------------- " Usage : " :[range]Sort " Sorts lines treating the entire line as one string " :[range]ColSort n " Sorts lines based on column n " :[range]ColSort n c " Sorts lines based on column n using c as column " " separator " ----------------------------------------------------------------------------- " Send feedback/bugs/suggestions on this to aziz@freeshell.org "============================================================================== func! Strcmp(str1, str2) if (a:str1 < a:str2) return -1 elseif (a:str1 > a:str2) return 1 else return 0 endif endfunction " Sort lines. SortR() is called recursively. func! SortR(start, end, cmp) if (a:start >= a:end) return endif let partition = a:start - 1 let middle = partition let partStr = getline((a:start + a:end) / 2) let i = a:start while (i <= a:end) let str = getline(i) exec "let result = " . a:cmp . "(str, partStr)" if (result <= 0) " Need to put it before the partition. Swap lines i and partition. let partition = partition + 1 if (result == 0) let middle = partition endif if (i != partition) let str2 = getline(partition) call setline(i, str2) call setline(partition, str) endif endif let i = i + 1 endwhile " Now we have a pointer to the "middle" element, as far as partitioning " goes, which could be anywhere before the partition. Make sure it is at " the end of the partition. if (middle != partition) let str = getline(middle) let str2 = getline(partition) call setline(middle, str2) call setline(partition, str) endif call SortR(a:start, partition - 1, a:cmp) call SortR(partition + 1, a:end, a:cmp) endfunc " To Sort a range of lines, pass the range to Sort() along with the name of a " function that will compare two lines. func! Sort(cmp) range call SortR(a:firstline, a:lastline, a:cmp) endfunc " :Sort takes a range of lines and sorts them. command! -nargs=0 -range Sort ,call Sort("Strcmp") "---------------------------------------------------------- " Additions by Aziz func! ColStrCmp(str1, str2) let modStr1 = substitute(a:str1, g:sortRegExMatch, g:sortReplPat, "") let modStr2 = substitute(a:str2, g:sortRegExMatch, g:sortReplPat, "") return Strcmp(modStr1, modStr2) endfunc func! ColSort(colNum,...) range if (a:0==0) let s = '\s' let w = '\S' else let s = a:1 let w = '[^'.a:1.']' endif "Build a regular expression to match the nth column number let g:sortRegExMatch = '^\('.s.'*\)\(' let cnt = 1 while (cnt < a:colNum) let g:sortRegExMatch = g:sortRegExMatch.w.'\+'.s.'*' let cnt = cnt + 1 endwhile let g:sortRegExMatch = g:sortRegExMatch.'\)\('.w.'\+'.s.'*\).*$' let g:sortReplPat = '\3' call SortR(a:firstline, a:lastline, "ColStrCmp") "unlet g:sortRegExMatch "unlet g:sortReplPat endfunc command! -nargs=1 -range ColSort ,call ColSort()