From 79bd6b4273325f891d2fcdb2a79ede59e313e414 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Tue, 30 May 2017 16:24:00 +0700 Subject: Formalise plugin: functions, autoload, tests --- autoload/novim_mode.vim | 287 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 autoload/novim_mode.vim (limited to 'autoload') diff --git a/autoload/novim_mode.vim b/autoload/novim_mode.vim new file mode 100644 index 0000000..f7408d3 --- /dev/null +++ b/autoload/novim_mode.vim @@ -0,0 +1,287 @@ +" 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 + \|| bufname('%') =~# 'NERD_tree_' + 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! + autocmd BufEnter * call s:InsertMode() + 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 : + + " 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 ^ + + " 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 + nnoremap + inoremap + nnoremap + inoremap + nnoremap + inoremap + 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 named 'p' register. + inoremap "pP + snoremap "pyi + inoremap "pY + snoremap "pxi + inoremap "pdd + " 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: 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 + " Clears highlighting. + " NB. Overriding ESC makes it harder to get into NORMAL mode. + inoremap :noh + 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 + inoremap "_dd + + " CTRL+ALT+d duplicates current line. + " NB. Uses the named 'd' register. + 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. +function! s:SetWrappedTextNavigation() + " Allow text to wrap in text files + au BufNewFile,BufRead *.txt,*.md,*.markdown setlocal linebreak spell + + " Make arrow keys move through wrapped lines + " TODO: + " * Make END key move to end of current wrapped piece of line. + " * Scroll window 1 wrapped soft line at a time rather an entire block of wrapped + " lines. + au BufNewFile,BufRead *.txt,*.md,*.markdown inoremap gk + au BufNewFile,BufRead *.txt,*.md,*.markdown inoremap gj +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 + " 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! 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 -- cgit v1.2.3-70-g09d2