" A fundamental question for this plugin is whether insertmode " is always relevant. This is where we try to get an answer. function! s:IsEditableBuffer() if &buftype ==# 'nofile' \|| !&modifiable \|| &readonly return 0 else return 1 endif endfunction " Make sure insert mode is the default mode only when opening/switching " to files that you want to edit. function! s:InsertMode() if s:IsEditableBuffer() == 1 exe "set insertmode" else exe "set noinsertmode" endif endfunction " Count number of open buffers. They don't have to be visible. function! s:CountListedBuffers() let bfr_count = 0 for bfr in range(1, bufnr("$")) if buflisted(bfr) \&& ! empty(bufname(bfr)) \|| getbufvar(bfr, '&buftype') ==# 'help' let bfr_count += 1 endif endfor return bfr_count endfunction " The number of visible lines in the current buffer. " TODO: Include wrapped lines in the total, so that we can start scrolling " through *visible* lines rather than file lines. function! s:BufferLines() return line('w$') - line('w0') endfunction function! s:InsertAndSelectionBehaviour() " Intelligently set/unset insertmode augroup start_insertmode autocmd! if has('timers') == 1 " The timer here delays the call to check whether the current buffer " is an editable one. Without the delay, the check is often too early " to correctly get the value of `&buftype`, etc. autocmd BufEnter * call timer_start(1, {->execute('call s:InsertMode()')}) else autocmd BufEnter * call s:InsertMode() endif augroup END " Mostly changes the way selection works. " See: http://vimdoc.sourceforge.net/htmldoc/gui.html#:behave " An extract from the docs about the difference between `behave mswin` " and `behave xterm`: " mswin xterm " 'selectmode' 'mouse,key' '' " 'mousemodel' 'popup' 'extend' " 'keymodel' 'startsel,stopsel' '' " 'selection' 'exclusive' 'inclusive' behave mswin " Make 'v' commands default to Visual mode. " Not sure how useful this is because the mappings that use 'v'-based " commands don't seem to follow this option. Thus why you will see " after some selection-based commands to switch from Visual to Selection " Mode. So might be better to give experienced users who are pressing " 'v' in normal mode the expected behaviour. set selectmode+=cmd endfunction " All shortcuts in one function so they can be more easily controlled. function! g:SetNoVimModeShortcuts() " Basic interactions with the editor if g:novim_mode_use_general_app_shortcuts == 1 " CTRL+q to completely exit vim inoremap :call novim_mode#ExitVim() snoremap :call novim_mode#ExitVim() nnoremap :call novim_mode#ExitVim() " CTRL+n for new file inoremap :edit " CTRL+o to open file " TODO: hook into netrw or NERDTree inoremap :edit " CTRL+s saves inoremap :update " Goto line number inoremap :call novim_mode#GotoLine() " ALT+; for command prompt inoremap : snoremap : inoremap : snoremap : nnoremap : nnoremap : " replaces native for one-time normal mode commands. inoremap snoremap endif " General fixes to editor behaviour if g:novim_mode_use_editor_fixes == 1 " Fix HOME to go back to the first non-whitespace character of the line. inoremap ^ " The same but for selection behaviour inoremap ^ snoremap ^ " Tweaks PageUp behaviour to get cursor to first line on top page inoremap :call novim_mode#PageUp() endif " Move between splits, panes, windows, etc and close them if g:novim_mode_use_pane_controls == 1 inoremap snoremap nnoremap inoremap snoremap nnoremap inoremap snoremap nnoremap inoremap snoremap nnoremap " This allows unsaved buffers to be kept in the background. set hidden " CTRL+w to delete current pane-like things. inoremap :call novim_mode#ClosePane() snoremap :call novim_mode#ClosePane() nnoremap :call novim_mode#ClosePane() end " Selecting, copy, paste, etc if g:novim_mode_use_copypasting == 1 " One of those curious features of Vim: without `onemore` when pasting " at the end of a line, pasted text gets put *before* the cursor. set virtualedit=onemore " NB. All these use the system clipboard. inoremap :call novim_mode#Paste() " The odd here is because one-off Normal Mode commands " don't seem to work as expected when some text is selected. Also just " using on its own seems to cause weird behaviour too. snoremap :call novim_mode#Paste() cnoremap " snoremap "+ygv inoremap "+Y snoremap "+xi inoremap "+dd " Select word under cursor inoremap viw " Select current line inoremap V " Append next line to selection snoremap gj " CTRL-A for selecting all text inoremap gggHG snoremap gggHG endif " Indenting if g:novim_mode_use_indenting == 1 " TODO: In Neovim TAB doesn't work in mswin selection mode, but SHIFT+TAB does?? snoremap >gv inoremap snoremap >gv " Unindenting snoremap snoremap / " Find selected word under cursor snoremap y/" " Find next inoremap n " Find previous inoremap N " Find and replace inoremap :%s/[FIND]/[REPLACE]/g endif " Undo/redo if g:novim_mode_use_undoing == 1 " Use for native terminal backgrounding. " The s used in the `snoremap` commands seem to prevent the selection " process itself being put in the undo history - so now the undo actually undoes " the last *text* activity. inoremap u snoremap u " Map CTRL+u as well for now just because by default it deletes the line above " the cursor. inoremap u snoremap u " Redo inoremap snoremap endif " Useful, but not necessarily core or conventional, shortcuts for manipulating " text. if g:novim_mode_use_text_tricks == 1 " CTRL+ALTt+k deletes the current line under the cursor " TODO: Doesn't work in terminal vim, even with vim-fixkey inoremap "_dd " CTRL+ALT+d duplicates current line. " NB. Uses the named 'd' register. " TODO: Doesn't work in terminal vim, even with vim-fixkey inoremap "dyy"dp " CTRL+DOWN/UP moves the current/selected line(s) up and down inoremap :m -2 snoremap :m '<-2gv=gv inoremap :m +1 snoremap :m '>+1gv=gv endif endfunction " By default Vim treats wrapped text as a single line even though it may " appear as many lines on screen. So here we try to make wrapped text behave " more conventionally. Please add any new types you might come across. function! s:SetWrappedTextNavigation() autocmd BufNewFile,BufRead *.{ \md, \mdown, \markdown, \txt, \textile, \rdoc, \org, \creole, \mediawiki \} setlocal filetype=txt autocmd FileType \ \rst, \asciidoc, \pod, \txt \ call s:WrappedTextBehaviour() endfunction function! s:WrappedTextBehaviour() " Allow text to wrap in text files setlocal linebreak wrap " Make arrow keys move through wrapped lines " TODO: " * Scroll window 1 wrapped soft line at a time rather than entire block " of wrapped lines -- I'm as good as certain this will need a patch to " (n)vim's internals. inoremap gk inoremap gj " For selection behaviour snoremap gk snoremap gj " HOME/END for *visible* lines, not literal lines inoremap g^ inoremap g$ " For selection behaviour inoremap g^ snoremap g^ inoremap g$ snoremap g$ endfunction " Try to intuitively and intelligently close things like buffers, splits, " panes, quicklist, etc, basically anything that looks like a pane. function! novim_mode#ClosePane() if s:IsEditableBuffer() == 1 " TODO: These aren't actually formally associated with a buffer, although " conceptually they often are (eg; linting errors, file search). " Close any location lists on screen. exe "lclose" " Close any quickfix lists on screen. exe "cclose" if s:CountListedBuffers() > 1 " By default if the buffer is the only one on screen, closing it closes the " tab/window. So this little trick does a switch to the next buffer, " then closes the previous buffer. exe "bp\|bd #" else quit endif else quit endif endfunction " TODO: Mention any unsaved buffers function! novim_mode#ExitVim() let l:confirmed = confirm('Do you really want to quit Vim?', "&Yes\n&No", 2) if l:confirmed == 1 quitall! endif endfunction function! novim_mode#GotoLine() let l:line_number = input('Goto line: ') execute line_number endfunction " Just to get PAGEUP to move to the first line when on the first page. function! novim_mode#PageUp() " If current line is higher than the size of the buffer if line(".") > s:BufferLines() " Normal PageUp execute "normal! \" else " Goto first line execute "normal! gg" endif endfunction function! novim_mode#Paste() set paste execute 'normal! "+P' set nopaste call feedkeys("\") endfunction function! g:novim_mode#StartNoVimMode() call s:InsertAndSelectionBehaviour() if g:novim_mode_use_better_wrap_navigation == 1 call s:SetWrappedTextNavigation() endif if g:novim_mode_use_shortcuts == 1 call g:SetNoVimModeShortcuts() endif endfunction