" Press \r to start rotating lines and <C-c> (Control+c) to stop. function! s:RotateString(string) let split_string = split(a:string, '\zs') return join(split_string[-1:] + split_string[:-2], '') endfunction function! s:RotateLine(line, leading_whitespace, trailing_whitespace) return substitute( \ a:line, \ '^\(' . a:leading_whitespace . '\)\(.\{-}\)\(' . a:trailing_whitespace . '\)$', \ '\=submatch(1) . <SID>RotateString(submatch(2)) . submatch(3)', \ '' \ ) endfunction function! s:RotateLines() let saved_view = winsaveview() let first_visible_line = line('w0') let last_visible_line = line('w$') let lines = getline(first_visible_line, last_visible_line) let leading_whitespace = map( \ range(len(lines)), \ 'matchstr(lines[v:val], ''^\s*'')' \ ) let trailing_whitespace = map( \ range(len(lines)), \ 'matchstr(lines[v:val], ''\s*$'')' \ ) try while 1 " <C-c> to exit let lines = map( \ range(len(lines)), \ '<SID>RotateLine(lines[v:val], leading_whitespace[v:val], trailing_whitespace[v:val])' \ ) call setline(first_visible_line, lines) redraw sleep 50m endwhile finally if &modified silent undo endif call winrestview(saved_view) endtry endfunction nnoremap <silent> <Plug>(RotateLines) :<C-u>call <SID>RotateLines()<CR> nmap \r <Plug>(RotateLines)