From cbfe86fbd57c04e276e8dc53b4d0a94277677301 Mon Sep 17 00:00:00 2001 From: Dwayne Litzenberger Date: Sat, 22 Mar 2014 18:16:54 -0700 Subject: [PATCH] Squashed 'bundle/QFEnter/' content from commit 31f93f7 git-subtree-dir: bundle/QFEnter git-subtree-split: 31f93f78c418ee17a1fbe0d4ba0f128dd33fdf2f --- .gitignore | 2 + README.md | 60 +++++++++++ autoload/QFEnter.vim | 165 ++++++++++++++++++++++++++++++ doc/QFEnter.txt | 234 +++++++++++++++++++++++++++++++++++++++++++ plugin/QFEnter.vim | 76 ++++++++++++++ 5 files changed, 537 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 autoload/QFEnter.vim create mode 100644 doc/QFEnter.txt create mode 100644 plugin/QFEnter.vim diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..05eef1c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +tags +video/* diff --git a/README.md b/README.md new file mode 100644 index 0000000..002d70d --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# QFEnter + +QFEnter allows you to open a Quickfix item in a window you choose. +You can choose the window by giving it a focus just before jumping to Quickfix window. +You can also open multiple items at once by including them in the visual block. + +A normal mode example: +![qfenter](https://f.cloud.github.com/assets/5915359/1632228/bb76dc72-5774-11e3-83d1-2933b95d5b81.gif) + +A visual mode example: +![qfentervisualopt](https://f.cloud.github.com/assets/5915359/2006385/61c6f720-8717-11e3-806b-d0f276af3ef9.gif) + +## Usage + +In Quickfix window, + +**\**, **\<2-LeftMouse\>** +*Normal mode* : Open an item under cursor in a previously focused window. +*Visual mode* : Open items in visual block in a previously focused window. As a result, the last item appears in the window. + +**\\** +*Normal mode* : Open an item under cursor in a new vertical split from a previously focused window. +*Visual mode* : Open items in visual block in a sequence of new vertical splits from a previously focused window. + +**\\** +*Normal mode* : Open an item under cursor in a new horizontal split from a previously focused window. +*Visual mode* : Open items in visual block in a sequence of new horizontal splits from a previously focused window. + +**\\** +*Normal mode* : Open an item under cursor in a new tab. +*Visual mode* : Open items in visual block in a sequence of new tabs. +Quickfix window is automatically opened in the new tab to help you open other Quickfix items. + +You can change the key mappings in your .vimrc. The default setting is, +``` +let g:qfenter_open_map = ['', '<2-LeftMouse>'] +let g:qfenter_vopen_map = [''] +let g:qfenter_hopen_map = [''] +let g:qfenter_topen_map = [''] +``` + +## Motivation + +Default opening methods for QuickFix items are quite inconvenient, + +- You cannot select a window in which a file is opened when you press `` in Quickfix. + + > Hitting the \ key or double-clicking the mouse on a line has the same effect. The +file containing the error is opened **in the window above the quickfix window**. +*`:help quickfix`* + + It is inconsistent with other Quickfix commands like `:cnext` and `:cprev` which open a file in a previously focused window. + +- You also cannot specify the window when you use `Ctrl-W `, +because Vim always create a new horizontal split window above Quickfix window and open a file in it. +There is even no command for 'open in new vertical split window'. + +They are confusing and bother me every time, so I wrote a simple plugin to make up for these weak points. +It's name comes from the most basic way to open a file from Quickfix window - the `` key. + diff --git a/autoload/QFEnter.vim b/autoload/QFEnter.vim new file mode 100644 index 0000000..8f063b5 --- /dev/null +++ b/autoload/QFEnter.vim @@ -0,0 +1,165 @@ +" File: autoload/QFEnter.vim +" Description: Open a Quickfix item in a window you choose. +" Author: yssl +" License: MIT License + +" functions +function! s:ExecuteCC(lnumqf) + let cc_cmd = substitute(g:qfenter_cc_cmd, '##', a:lnumqf, "") + execute cc_cmd +endfunction + +function! s:ExecuteCN(count) + let cn_cmd = g:qfenter_cn_cmd + execute cn_cmd +endfunction + +function! s:ExecuteCP(count) + let cp_cmd = g:qfenter_cp_cmd + execute cp_cmd +endfunction + +function! QFEnter#OpenQFItem(wintype, opencmd, isvisual) + let qfbufnr = bufnr('%') + let qflnum = line('.') + + if a:isvisual + let vblnum2 = getpos("'>")[1] + endif + + call s:OpenQFItem(a:wintype, a:opencmd, qflnum) + + if a:isvisual + if qflnum==vblnum2 + if g:qfenter_keep_quickfixfocus[a:opencmd]==1 + redraw + let qfwinnr = bufwinnr(qfbufnr) + exec qfwinnr.'wincmd w' + endif + else + let qfwinnr = bufwinnr(qfbufnr) + exec qfwinnr.'wincmd w' + endif + else + if g:qfenter_keep_quickfixfocus[a:opencmd]==1 + redraw + let qfwinnr = bufwinnr(qfbufnr) + exec qfwinnr.'wincmd w' + endif + endif +endfunction + +"wintype: 'open', 'vert', 'horz', 'tab' +"opencmd: 'cc', 'cn', 'cp' +function! s:OpenQFItem(wintype, opencmd, qflnum) + let lnumqf = a:qflnum + + " arrange a window or tab in which quickfix item to be opened + if a:wintype==#'open' + wincmd p + elseif a:wintype==#'vert' + wincmd p + vnew + elseif a:wintype==#'horz' + wincmd p + new + elseif a:wintype==#'tab' + let qfview = winsaveview() + + let modifier = '' + let widthratio = winwidth(0)*&lines + let heightratio = winheight(0)*&columns + if widthratio > heightratio + let modifier = modifier.'' + let qfresize = 'resize '.winheight(0) + else + let modifier = modifier.'vert' + let qfresize = 'vert resize '.winwidth(0) + endif + + if winnr() <= winnr('$')/2 + let modifier = modifier.' topleft' + else + let modifier = modifier.' botright' + endif + + tabnew + endif + + " save current tab or window to check after switchbuf applied when executing cc, cn, cp commands + let before_tabnr = tabpagenr() + let before_winnr = winnr() + + " execute vim quickfix open commands + if a:opencmd==#'open' + call s:ExecuteCC(lnumqf) + elseif a:opencmd==#'cnext' + call s:ExecuteCN(lnumqf) + elseif a:opencmd==#'cprev' + call s:ExecuteCP(lnumqf) + endif + + " check if switchbuf applied. + " if useopen or usetab are applied with new window or tab command, close the newly opened tab or window. + let after_tabnr = tabpagenr() + let after_winnr = winnr() + if (match(&switchbuf,'useopen')>-1 || match(&switchbuf,'usetab')>-1) + if a:wintype==#'tab' + if before_tabnr!=after_tabnr + call s:JumpToTab(before_tabnr) + call s:CloseTab(after_tabnr) + endif + elseif a:wintype==#'vert'|| a:wintype==#'horz' + if before_tabnr!=after_tabnr |"when 'usetab' applied + call s:JumpToTab(before_tabnr) + call s:CloseWin(after_winnr) + call s:JumpToTab(after_tabnr) + elseif before_winnr!=after_winnr + call s:JumpToWin(before_winnr) + call s:CloseWin(after_winnr) + endif + endif + endif + "echo before_tabnr after_tabnr + "echo before_winnr after_winnr + + " restore quickfix window when tab mode + if a:wintype==#'tab' + if g:qfenter_enable_autoquickfix + exec modifier 'copen' + exec qfresize + call winrestview(qfview) + wincmd p + endif + endif +endfunction + +fun! s:CloseWin(return_winnr) + let prevwinnr = a:return_winnr + if prevwinnr > winnr() + let prevwinnr = prevwinnr - 1 + endif + + quit + + call s:JumpToWin(prevwinnr) +endfun + +fun! s:JumpToWin(winnum) + exec a:winnum.'wincmd w' +endfun + +fun! s:CloseTab(return_tabnr) + let prevtabnr = a:return_tabnr + if prevtabnr > tabpagenr() + let prevtabnr = prevtabnr - 1 + endif + + tabclose + + call s:JumpToTab(prevtabnr) +endfun + +fun! s:JumpToTab(tabnum) + exec 'tabnext' a:tabnum +endfun diff --git a/doc/QFEnter.txt b/doc/QFEnter.txt new file mode 100644 index 0000000..ccb3ed0 --- /dev/null +++ b/doc/QFEnter.txt @@ -0,0 +1,234 @@ +*QFEnter.txt* Open a Quickfix item in a window you choose. +*QFEnter* + +Author: yssl + +============================================================================== +Contents *QFEnter-contents* + + 1. Introduction ............................... |QFEnter-intro| + 2. Usage ...................................... |QFEnter-usage| + 3. Options .................................... |QFEnter-options| + 4. |switchbuf| option ......................... |QFEnter-switchbuf| + 5. Changelog .................................. |QFEnter-changelog| + +============================================================================== +1. Introduction *QFEnter-intro* + +QFEnter allows you to open a Quickfix item in a window you choose. +You can choose the window by giving it a focus just before jumping to Quickfix window. +You can also open multiple items at once by including them in the visual block. + +Default opening methods for QuickFix items are quite inconvenient, + +- You cannot select a window in which a file is opened when you press `` in Quickfix. + + > Hitting the key or double-clicking the mouse on a line has the same effect. + The file containing the error is opened **in the window above the quickfix window**. + `from :help quickfix` + + It is inconsistent with other Quickfix commands like `:cnext` and `:cprev` + which open a file in a previously focused window. + +- You also cannot specify the window when you use `Ctrl-W `, +because Vim always create a new horizontal split window above Quickfix window and +open a file in it. +There is even no command for 'open in a new vertical split window'. + +They are confusing and bothers me every time, so I wrote a simple plugin +to make up for these weak points. +It's name comes from the most basic way to open a file from Quickfix window +- the `` key. + +============================================================================== +2. Usage *QFEnter-usage* + +In |Quickfix| window, + +, <2-LeftMouse> (open) +Normal mode : Open an item under cursor in a previously focused window. +Visual mode : Open items in visual block in a previously focused window. As a result, the last item appears in the window. + + (vopen) +Normal mode : Open an item under cursor in a new vertical split from a previously focused window. +Visual mode : Open items in visual block in a sequence of new vertical splits from a previously focused window. + + (hopen) +Normal mode : Open an item under cursor in a new horizontal split from a previously focused window. +Visual mode : Open items in visual block in a sequence of new horizontal splits from a previously focused window. + + (topen) +Normal mode : Open an item under cursor in a new tab. +Visual mode : Open items in visual block in a sequence of new tabs. +Quickfix window is automatically opened in the new tab to help you open other Quickfix items. + +You can change the key mappings in your .vimrc (see |QFEnter-options|). + +============================================================================== +3. Options *QFEnter-options* + +|QFEnter| mappings are enabled only in |Quickfix| window. + +*g:qfenter_open_map* +Key mappings to open items under cursor or in visual block in a previously focused window. +Default: > + let g:qfenter_open_map = ['', '<2-LeftMouse>'] +< + +*g:qfenter_vopen_map* +Key mappings to open items under cursor or in visual block in new vertical splits from a previously +focused window. +Default: > + let g:qfenter_vopen_map = [''] +< + +*g:qfenter_hopen_map* +Key mappings to open items under cursor or in visual block in new horizontal splits from a previously +focused window. +Default: > + let g:qfenter_hopen_map = [''] +< + +*g:qfenter_topen_map* +Key mappings to open items under cursor or in visual block in new tabs. +Default: > + let g:qfenter_topen_map = [''] +< + +*g:qfenter_keep_quickfixfocus* +If you want Quickfix window to keep focus after opening items, you can set this +option for each opening command. +Default: > + let g:qfenter_keep_quickfixfocus = { + \'open':0, + \'cnext':0, + \'cprev':0, + \} +< + +*g:qfenter_enable_autoquickfix* +Enable or disable automatic opening of Quickfix window when 'open in a new +tab' command is executed. +If enabled, Quickfix window is automatically opened in the new tab with its +original size, view and position to help you open other Quickfix items. +(not correctly, but smartly determined) +Default: > + let g:qfenter_enable_autoquickfix = 1 +< + +*g:qfenter_cc_cmd* +QFEnter internally uses |:cc| command. +If you're using your custom "cc" command instead of vim's default |:cc|, you +can register it by setting this option and make QFEnter use it. +The option should have "##" which is converted to the line number later. +Default: > + let g:qfenter_cc_cmd = '##cc' +< + +*g:qfenter_cnext_map* +*g:qfenter_vcnext_map* +*g:qfenter_hcnext_map* +*g:qfenter_tcnext_map* +Key mappings to open items using the :cnext command. +Disabled by default. +Default: > + let g:qfenter_cnext_map = [] + let g:qfenter_vcnext_map = [] + let g:qfenter_hcnext_map = [] + let g:qfenter_tcnext_map = [] +< + +*g:qfenter_cprev_map* +*g:qfenter_vcprev_map* +*g:qfenter_hcprev_map* +*g:qfenter_tcprev_map* +Key mappings to open items using the :cprev command. +Disabled by default. +Default: > + let g:qfenter_cprev_map = [] + let g:qfenter_vcprev_map = [] + let g:qfenter_hcprev_map = [] + let g:qfenter_tcprev_map = [] +< + +*g:qfenter_cn_cmd*, *g:qfenter_cp_cmd* +If you're using your custom "cn" or "cp" command instead of vim's default +|:cn| or |:cp|, you can register them by setting these options. +Default: > + let g:qfenter_cn_cmd = 'cn' + let g:qfenter_cp_cmd = 'cp' +< + +============================================================================== +4. |switchbuf| option *QFEnter-switchbuf* + +You can control QFEnter's behavior with vim's |switchbuf| option when opening an item. +When each opening command is invoked, QFEnter checks |switchbuf| option and adjusts its behavior. +|switchbuf| option can have five values; (none), useopen, usetab, split, newtab. + +For example, you can set the option in your .vimrc as following: +> + set switchbuf=useopen +< + +The defalut value is (none), meaning that: +> + set switchbuf= +< + +If there is no already opened window of the buffer for the item you selected, +QFEnter opens the item with its default behavior as decribed in |QFEnter-usage|. + +Otherwise, |switchbuf| option choose the window to open the item in. +You can refer :help switchbuf for more details. + +============================================================================== +5. Changelog *QFEnter-changelog* + +2.2.1 2014/03/17 + - update document for 'switchbuf' option. + +2.2.0 2014/03/17 + - now QFEnter supports vim's 'switchbuf' option. + if you change 'switchbuf' option, QFEnter adapts its behavior to the changed option. + - thanks to sergey-vlasov! + +2.1.0 2014/01/28 + - subdivide g:qfenter_keep_quickfixfocus option for each command. + e.g. g:qfenter_keep_quickfixfocus.open, g:qfenter_keep_quickfixfocus.cnext, + g:qfenter_keep_quickfixfocus.cprev + - bug fix : not updated window for already opened file when g:qfenter_keep_quickfixfocus==1 + - thanks to mMontu! + +2.0.0 2014/01/27 + - visual mode support to open multiple Quickfix items at once + - add option to keep focus in Quicifix window after opening items + (g:qfenter_keep_quickfixfocus) + - support :cnext and :cprev command to open items + +1.3.0 2013/12/10 + - improve auto quickfix open when 'open in new tab' + - restore view(cursor position, scroll..) of quickfix window to auto-opened quickfix window + - restore size of quickfix window to auto-opened quickfix window + - now you don't need to provide g:qfenter_copen_modifier option. + QFEnter now smartly determine whether the new quickfix window is botright or topleft, vertical or horizontal. + - change g:qfenter_ttopen_map option name to g:qfenter_topen_map (backward + compatibility ismaintained) + - remove '' from default mapping + +1.2.0 2013/12/08 + - now, Quickfix window is automatically opened after "open in a new tab" + - add options about Quickfix auto opening + - add one more default mapping for "open in a new tab" + - code refactoring + +1.1.1 2013/12/06 + - change default mapping for "open a file in a new tab" + +1.1.0 2013/12/06 + - add new features + : open a file under cursor in a new tab. + : register custom "cc" command with g:qfenter_cc_cmd + +1.0.0 2013/11/24 + - first version diff --git a/plugin/QFEnter.vim b/plugin/QFEnter.vim new file mode 100644 index 0000000..e1d8c1d --- /dev/null +++ b/plugin/QFEnter.vim @@ -0,0 +1,76 @@ +" File: plugin/QFEnter.vim +" Description: Open a Quickfix item in a window you choose. +" Author: yssl +" License: MIT License + +if exists("g:loaded_qfenter") || &cp + finish +endif +let g:loaded_qfenter = 1 +let s:keepcpo = &cpo +set cpo&vim +""""""""""""""""""""""""""""""""""""""""""""" + +" global variables +if !exists('g:qfenter_open_map') | let g:qfenter_open_map = ['', '<2-LeftMouse>'] | endif +if !exists('g:qfenter_vopen_map') | let g:qfenter_vopen_map = [''] | endif +if !exists('g:qfenter_hopen_map') | let g:qfenter_hopen_map = [''] | endif +if !exists('g:qfenter_topen_map') | let g:qfenter_topen_map = [''] | endif + +if !exists('g:qfenter_cnext_map') | let g:qfenter_cnext_map = [] | endif +if !exists('g:qfenter_vcnext_map') | let g:qfenter_vcnext_map = [] | endif +if !exists('g:qfenter_hcnext_map') | let g:qfenter_hcnext_map = [] | endif +if !exists('g:qfenter_tcnext_map') | let g:qfenter_tcnext_map = [] | endif + +if !exists('g:qfenter_cprev_map') | let g:qfenter_cprev_map = [] | endif +if !exists('g:qfenter_vcprev_map') | let g:qfenter_vcprev_map = [] | endif +if !exists('g:qfenter_hcprev_map') | let g:qfenter_hcprev_map = [] | endif +if !exists('g:qfenter_tcprev_map') | let g:qfenter_tcprev_map = [] | endif + +if !exists('g:qfenter_cc_cmd') | let g:qfenter_cc_cmd = '##cc' | endif +if !exists('g:qfenter_cn_cmd') | let g:qfenter_cn_cmd = 'cn' | endif +if !exists('g:qfenter_cp_cmd') | let g:qfenter_cp_cmd = 'cp' | endif + +if !exists('g:qfenter_enable_autoquickfix') + let g:qfenter_enable_autoquickfix = 1 +endif + +if !exists('g:qfenter_keep_quickfixfocus') + let g:qfenter_keep_quickfixfocus = { + \'open':0, + \'cnext':0, + \'cprev':0, + \} +endif + +" autocmd +augroup QFEnterAutoCmds + autocmd! + + autocmd FileType qf call s:RegisterMapping(g:qfenter_open_map, "open","open") + autocmd FileType qf call s:RegisterMapping(g:qfenter_vopen_map, "vert","open") + autocmd FileType qf call s:RegisterMapping(g:qfenter_hopen_map, "horz","open") + autocmd FileType qf call s:RegisterMapping(g:qfenter_topen_map, "tab","open") + + autocmd FileType qf call s:RegisterMapping(g:qfenter_cnext_map, "open","cnext") + autocmd FileType qf call s:RegisterMapping(g:qfenter_vcnext_map, "vert","cnext") + autocmd FileType qf call s:RegisterMapping(g:qfenter_hcnext_map, "horz","cnext") + autocmd FileType qf call s:RegisterMapping(g:qfenter_tcnext_map, "tab","cnext") + + autocmd FileType qf call s:RegisterMapping(g:qfenter_cprev_map, "open","cprev") + autocmd FileType qf call s:RegisterMapping(g:qfenter_vcprev_map, "vert","cprev") + autocmd FileType qf call s:RegisterMapping(g:qfenter_hcprev_map, "horz","cprev") + autocmd FileType qf call s:RegisterMapping(g:qfenter_tcprev_map, "tab","cprev") +augroup END + +" functions +function! s:RegisterMapping(keymap, wintype, opencmd) + for key in a:keymap + execute 'nnoremap '.key.' :call QFEnter#OpenQFItem("'.a:wintype.'","'.a:opencmd.'",0)' + execute 'vnoremap '.key.' :call QFEnter#OpenQFItem("'.a:wintype.'","'.a:opencmd.'",1)' + endfor +endfunction + +"""""""""""""""""""""""""""""""""""""""""""" +let &cpo= s:keepcpo +unlet s:keepcpo