├── LICENSE ├── README.md ├── autoload └── smartq.vim ├── init.vim └── plugin └── smartq.vim /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | vim-smartq 4 | Copyright © 2021 Mark Lucernas 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the "Software"), 8 | to deal in the Software without restriction, including without limitation 9 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | and/or sell copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included 14 | in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 20 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 22 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vim-smartq 2 | 3 | Master key for quitting vim buffers. 4 | 5 | Exit/Delete buffer with respect to window splits and tabs, and other types of 6 | buffer. 7 | 8 | ## Features 9 | 10 | Preserve splits across tabs 11 | 12 | ![Preserve Splits](https://i.imgur.com/uKRWrjS.gif) 13 | 14 | [Zen-mode](https://github.com/folke/zen-mode.nvim) Integration 15 | 16 | ![Zen-mode Integration](https://i.imgur.com/XuZZjaG.gif) 17 | 18 | [Goyo](https://github.com/junegunn/goyo.vim) Integration 19 | 20 | ![Goyo Integration](https://i.imgur.com/sB70XEK.gif) 21 | 22 | Close all diff buffers 23 | 24 | ![Diff](https://i.imgur.com/qSTQfGl.gif) 25 | 26 | Additional features 27 | 28 | - Close all splits in current tab when one empty modifiable buffer remaining 29 | with multiple splits. 30 | - Auto wipe empty buffers when deleting/wiping a buffer 31 | 32 | ## Installation 33 | 34 | Using [vim-plug](https://github.com/junegunn/vim-plug) 35 | 36 | ```vim 37 | Plug 'marklcrns/vim-smartq' 38 | ``` 39 | 40 | Using [dein](https://github.com/Shougo/dein.vim) 41 | 42 | ```vim 43 | call dein#add('marklcrns/vim-smartq') 44 | ``` 45 | 46 | other package managers may be used as well. 47 | 48 | ## Usage 49 | 50 | Plug and play. Automatically remap macro record `q` to `Q`, then map `q` to 51 | `(smartq_this)` and `` to `(smartq_this_force)` 52 | 53 | ```vim 54 | :SmartQ {buffer} " Smart quit (buffer name/number, optional) 55 | :SmartQ! {buffer} " Same as above but forced 56 | :SmartQSave {buffer} " Smart save before quit (buffer name/number, optional) 57 | :SmartQWipeEmpty " Wipe all empty (untitled) buffers 58 | :SmartQWipeEmpty! " Same as above but forced 59 | :SmartQCloseSplits " Close all splits excluding non-modifiable buffers 60 | ``` 61 | 62 | > Tip: SmartQ(!) accepts both buffer name and buffer number (see :buffers). Also 63 | > supports tab completion. 64 | 65 | ## Mappings 66 | 67 | ```vim 68 | nmap (smartq_this) " :SmartQ 69 | nmap (smartq_this_save) " :SmartQSave 70 | nmap (smartq_this_force) " :SmartQ! 71 | nmap (smartq_wipe_empty) " :SmartQWipeEmpty 72 | nmap (smartq_wipe_empty_force) " :SmartQWipeEmpty! 73 | nmap (smartq_close_splits) " :SmartQCloseSplits 74 | ``` 75 | 76 | ## Customization 77 | 78 | ```vim 79 | " Default Settings 80 | " ----- 81 | 82 | " Default mappings: 83 | " Remaps normal mode macro record q to Q 84 | " nnoremap Q q 85 | " nmap q (smartq_this) 86 | " nmap (smartq_this_force) 87 | let g:smartq_default_mappings = 1 88 | 89 | " Excluded buffers to disable SmartQ and to preserve windows when closing splits 90 | " on excluded buffers. Non-modifiable buffers are preserved by default. 91 | let g:smartq_exclude_filetypes = [ 92 | \ 'fugitive' 93 | \ ] 94 | let g:smartq_exclude_buftypes= [ 95 | \ '' 96 | \ ] 97 | 98 | " Quit buffers using :q command. Non-modifiable and readonly file uses :q 99 | let g:smartq_q_filetypes = [ 100 | \ 'diff', 'git', 'gina-status', 'gina-commit', 'snippets', 101 | \ 'floaterm' 102 | \ ] 103 | let g:smartq_q_buftypes = [ 104 | \ 'quickfix', 'nofile' 105 | \ ] 106 | 107 | " Wipe buffers using :bw command. Wiped buffers are removed from jumplist 108 | " Default :bd 109 | let g:smartq_bw_filetypes = [ 110 | \ '' 111 | \ ] 112 | let g:smartq_bw_buftypes = [ 113 | \ '' 114 | \ ] 115 | 116 | " Automatically wipe empty (with no changes) buffer(s) 117 | let g:smartq_auto_wipe_emtpy = 1 118 | " Best attemp to prevent exiting editor when left with an empty modifiable buffer 119 | let g:smartq_no_exit = 0 120 | " Automatically close splits when left with 1 modifiable buffer 121 | let g:smartq_auto_close_splits = 0 122 | 123 | " --- PLUGIN INTEGRATIONS 124 | " When a plugin is disabled, use built-in fallbacks 125 | 126 | " Enable Goyo 127 | let g:smartq_goyo_integration = 1 128 | " Enable Zen-mode 129 | let g:smartq_zenmode_integration = 1 130 | ``` 131 | 132 | ## SmartQ Quit Prioritization 133 | 134 | Ordered list of SmartQ quit conditions. Once `SmartQ` command is executed, it 135 | will find and **ONLY EXECUTE ONE** condition from the list below. 136 | 137 | 1. **Delete** (`bd`) all `diff` buffers. Check: `:set diff?` 138 | 2. **Delete** (`bd`) [Zen-mode](https://github.com/folke/zen-mode.nvim) buffer 139 | 2. **Delete** (`bd`) [Goyo](https://github.com/junegunn/goyo.vim) buffer 140 | 3. **Quit** (`q`) 141 | - `smartq_q_filetypes` or `smartq_q_buftypes` 142 | - `terminal` buffer 143 | - `nomodifiable` or `readonly` window 144 | - Exceptions: `smartq_exclude_filetypes`, `smartq_exclude_buftypes`, empty `filetype` and `buftype` 145 | 4. On final buffer 146 | i. **Close** (`close!`) all `modifiable` windows OR **Quit all** (`qa`) if empty buffer 147 | 5. On final buffer with `nomodifiable` window(s) 148 | i. **Quit all** (`qa`) if empty buffer 149 | 6. **Wipe** (`bw`) 150 | - `smartq_bw_filetypes` or `smartq_bw_buftypes` 151 | - Exceptions: `smartq_exclude_filetypes`, `smartq_exclude_buftypes`, empty `filetype` and `buftype` 152 | 7. Catch all: **Delete** (`bd`) buffer. Check: `:buffers` 153 | 154 | See `diff`, `modifiable`, `filetype`, `buftype`, `buffers` 155 | 156 | 157 | ## Credits 158 | 159 | - [cespare/vim-sbd](https://github.com/cespare/vim-sbd) 160 | - [moll/vim-bbye](https://github.com/moll/vim-bbye) 161 | - [Asheq/close-buffers.vim](https://github.com/Asheq/close-buffers.vim) 162 | 163 | -------------------------------------------------------------------------------- /autoload/smartq.vim: -------------------------------------------------------------------------------- 1 | " smartq.vim 2 | " Version: 1.4 3 | " 4 | " Description: 5 | " Sensibly close buffers with respect to alternate tabs and window splits, 6 | " and other types of buffer. 7 | " Features: 8 | " - Delete buffers with preserving tabs and window splits displaying the same 9 | " buffer to be deleted. Auto wipe empty buffer when deleting/wiping buffers. 10 | " - Keep tabs and window splits open with an empty buffer if pointing to 11 | " same buffer to be deleted. 12 | " - Prevents from deleting buffer if modified or in g:smartq_exclude_filetypes 13 | " and g:smartq_exclude_buftypes 14 | " - Handles diff splits, closing all diff buffer windows automatically. 15 | " - Goyo integration. Remain in Goyo tab when deleting buffers. Exists if only 16 | " one buffer remains. 17 | " Commands: 18 | " :SmartQ 19 | " :SmartQ! 20 | " :SmartQCloseSplits 21 | " :SmartQWipeEmpty 22 | " 23 | " Author: 24 | " Mark Lucernas 25 | " Date: 26 | " 2021-06-12 27 | " Licence: 28 | " MIT 29 | " 30 | " Refs: 31 | " smartq#smartq() 32 | " - https://github.com/cespare/vim-sbd 33 | " - https://github.com/Asheq/close-buffers.vim 34 | " - https://stackoverflow.com/a/29236158 35 | " - https://superuser.com/questions/345520/vim-number-of-total-buffers 36 | " smartq#wipe_empty_buffers() 37 | " - https://stackoverflow.com/a/10102604 38 | " s:new_tmp_buf() and s:str_to_bufnr() 39 | " - https://github.com/moll/vim-bbye/blob/master/plugin/bbye.vim 40 | 41 | if exists('g:smartq_loaded') 42 | finish 43 | endif 44 | let g:smartq_loaded = 1 45 | 46 | let s:save_cpo = &cpo 47 | set cpo&vim 48 | 49 | 50 | function! s:shift_win_buf_pointing_to_cur_buf(bufNr) 51 | let bufCount = len(getbufinfo({'buflisted':1})) 52 | let curTabNr = tabpagenr() 53 | 54 | if bufCount ==# 1 && bufname(a:bufNr) ==# '' 55 | return 56 | endif 57 | 58 | for i in range(1, tabpagenr('$')) 59 | silent execute 'tabnext ' . i 60 | if winnr('$') ># 1 61 | " Store active window nr to restore later 62 | let curWin = winnr() 63 | " Loop over windows pointing to curBuf 64 | let winnr = bufwinnr(a:bufNr) 65 | while (winnr >= 0) 66 | " Go to window and switch to next buffer 67 | silent execute winnr . 'wincmd w' 68 | if len(getbufinfo({'buflisted':1})) ==# 1 69 | call s:new_tmp_buf('!') 70 | else 71 | silent execute 'bnext' 72 | endif 73 | " Restore active window 74 | silent execute curWin . 'wincmd w' 75 | let winnr = bufwinnr(a:bufNr) 76 | endwhile 77 | endif 78 | endfor 79 | 80 | " Restore active tab 81 | silent execute 'tabn ' . curTabNr 82 | endfunction 83 | 84 | 85 | function! s:str_to_bufnr(buffer) 86 | if empty(a:buffer) " Current buffer 87 | return bufnr('%') 88 | elseif a:buffer =~# '^\d\+$' " Str bufnr to bufnr 89 | return bufnr(str2nr(a:buffer)) 90 | else " Bufname to bufnr 91 | return bufnr(a:buffer) 92 | endif 93 | endfunction 94 | 95 | 96 | function! s:new_tmp_buf(bang) 97 | silent execute 'enew' . a:bang 98 | setl noswapfile 99 | setl bufhidden=wipe 100 | setl buftype= 101 | endfunction 102 | 103 | 104 | function! s:del_buf(bufNr, bufDeleteCmd, bang) 105 | let command = a:bufDeleteCmd . a:bang . ' ' 106 | 107 | " Store listed buffers count 108 | let bufCount = len(getbufinfo({'buflisted':1})) 109 | 110 | " Prevent tabs and windows from closing if pointing to the same curBuf 111 | if getbufvar(a:bufNr, '&modifiable') 112 | call s:shift_win_buf_pointing_to_cur_buf(a:bufNr) 113 | endif 114 | 115 | silent execute command . a:bufNr 116 | 117 | if bufCount ># 1 || g:smartq_auto_close_splits ==# 1 118 | call smartq#wipe_empty_bufs(a:bang) 119 | endif 120 | " POSSIBLY UNREACHABLE: If left with non-modifiable buffer, create blank 121 | if !&modifiable 122 | call s:new_tmp_buf('!') 123 | endif 124 | endfunction 125 | 126 | 127 | " Quit all diff buffers 128 | function! s:close_diff_bufs(bang) 129 | for bufNr in range(1, bufnr('$')) 130 | if getwinvar(bufwinnr(bufNr), '&diff') == 1 131 | " Go to the diff buffer window and quit 132 | silent execute bufwinnr(bufNr) . 'wincmd w | ' . 'bd' . a:bang 133 | endif 134 | endfor 135 | endfunction 136 | 137 | 138 | " Hacky workaround to delete buffer while in Goyo mode without exiting and 139 | " to turn off Goyo mode when only one buffer exists 140 | function! s:del_goyo_buf(bang) 141 | let bufCount = len(getbufinfo({'buflisted':1})) 142 | if bufCount ># 1 143 | silent execute 'bn | ' . 'bd' . a:bang . '#' 144 | else 145 | silent execute 'q' . a:bang 146 | endif 147 | call smartq#wipe_empty_bufs('!') 148 | endfunction 149 | 150 | 151 | " Hacky workaround to delete buffer while in ZenMode without exiting and 152 | " to turn off Goyo mode when only one buffer exists 153 | function! s:del_zenmode_buf(bang) 154 | let bufCount = len(getbufinfo({'buflisted':1})) 155 | if bufCount ># 1 156 | silent execute 'bn | ' . 'bd' . a:bang . '#' 157 | else 158 | silent execute 'q' . a:bang 159 | endif 160 | call smartq#wipe_empty_bufs('!') 161 | endfunction 162 | 163 | 164 | " Count all modifiable splits 165 | function! s:count_mod_splits() 166 | let splitsCount = 0 167 | if winnr('$') ># 1 168 | for _ in range(1, winnr('$')) 169 | if &modifiable 170 | let splitsCount += 1 171 | endif 172 | " WARNING: toggles off ZenMode 173 | silent execute 'wincmd w' 174 | endfor 175 | return splitsCount 176 | endif 177 | 178 | return 1 179 | endfunction 180 | 181 | 182 | " Close all modifiable splits 183 | function! smartq#close_mod_splits(bang) 184 | if g:smartq_auto_close_splits ==# 0 && a:bang ==# '' 185 | return 186 | endif 187 | 188 | if s:count_mod_splits() ># 1 189 | for _ in range(1, winnr('$') - 1) 190 | if &modifiable 191 | silent execute 'close!' 192 | endif 193 | silent execute 'wincmd w' 194 | endfor 195 | return 1 196 | endif 197 | return 0 198 | endfunction 199 | 200 | 201 | function! s:is_buf_excl() 202 | let filetype = &filetype 203 | let buftype = &buftype 204 | if (filetype !=# '' && index(g:smartq_exclude_filetypes, filetype) >=# 0) 205 | \ || (buftype !=# '' && index(g:smartq_exclude_buftypes, buftype) >=# 0) 206 | return 1 207 | endif 208 | return 0 209 | endfunction 210 | 211 | 212 | function! s:is_buf_q() 213 | let filetype = &filetype 214 | let buftype = &buftype 215 | if buftype ==# 'terminal' 216 | return 0 217 | elseif (filetype !=# '' && index(g:smartq_q_filetypes, filetype) >=# 0) 218 | \ || (buftype !=# '' && index(g:smartq_q_buftypes, buftype) >=# 0) 219 | \ || !&modifiable || &readonly 220 | return 1 221 | endif 222 | return 0 223 | endfunction 224 | 225 | 226 | function! s:is_buf_bw() 227 | let filetype = &filetype 228 | let buftype = &buftype 229 | if (filetype !=# '' && index(g:smartq_bw_filetypes, filetype) >=# 0) 230 | \ || buftype ==# 'terminal' 231 | \ || (buftype !=# '' && index(g:smartq_bw_buftypes, buftype) >=# 0) 232 | return 1 233 | endif 234 | return 0 235 | endfunction 236 | 237 | function! s:is_floating(id) 238 | if has('nvim') 239 | let l:cfg = nvim_win_get_config(a:id) 240 | return !empty(l:cfg.relative) || l:cfg.external 241 | endif 242 | return 0 243 | endfunction 244 | 245 | function! s:is_goyo_active() 246 | return exists('#goyo') 247 | endfunction 248 | 249 | function! s:is_zenmode_active() 250 | if has('nvim') 251 | let is_active = execute("silent! lua print(require('zen-mode.view').is_open())") 252 | return stridx(is_active, 'true') !=# -1 253 | endif 254 | return 0 255 | endfunction 256 | 257 | function! s:echo_error(msg, newline) 258 | let message = '[vim-smartq] ERROR: ' . a:msg 259 | 260 | if a:newline ==# 1 261 | message = '\n' . message 262 | endif 263 | 264 | echohl WarningMsg | echom message | echohl None 265 | endfunction 266 | 267 | function! s:echo_info(msg, newline) 268 | let message = '[vim-smartq] INFO: ' . a:msg 269 | 270 | if a:newline ==# 1 271 | message = '\n' . message 272 | endif 273 | 274 | echom message 275 | endfunction 276 | 277 | function! s:echo_msg(msg, newline) 278 | let message = '[vim-smartq]: ' . a:msg 279 | 280 | if a:newline ==# 1 281 | message = '\n' . message 282 | endif 283 | 284 | echo message 285 | endfunction 286 | 287 | function! s:confirm_prompt(msg) 288 | call s:echo_msg(a:msg . ' [y/n] ', 0) 289 | let answer = nr2char(getchar()) 290 | 291 | if answer ==? 'y' 292 | return 1 293 | elseif answer ==? 'n' 294 | return 0 295 | elseif answer ==# '' 296 | call s:echo_error('Aborted!', 0) 297 | return 0 298 | else 299 | echo 'Please enter "y" or "n"' 300 | return s:confirm_prompt(a:msg) 301 | endif 302 | endfunction 303 | 304 | function! s:save_buf(bang, bufName) 305 | try 306 | exec 'w' . a:bang . ' ' . a:bufName 307 | " No file name 308 | catch E32 309 | let root = getcwd() . '/' 310 | let newfile = input('New filename: ' . root, '', 'file') 311 | 312 | if empty(newfile) 313 | call s:echo_error("Saving buffer '" . a:bufName . "' aborted!", 1) 314 | return 1 315 | elseif isdirectory(newfile) 316 | call s:echo_error(newfile . ' is a directory!', 1) 317 | return 2 318 | endif 319 | let dir=fnamemodify(newfile, ':h') 320 | if !isdirectory(dir) 321 | call mkdir(dir, 'p') 322 | endif 323 | exec 'w' . a:bang . ' ' . newfile 324 | return 0 325 | endtry 326 | 327 | call s:echo_error('Error writting to buffer ' . a:bufName . ' aborted!', 1) 328 | return 1 329 | endfunction 330 | 331 | 332 | function! smartq#wipe_empty_bufs(bang) 333 | if g:smartq_auto_wipe_emtpy ==# 0 && a:bang ==# '' 334 | return 0 335 | endif 336 | 337 | let emtpyBufs = filter(range(1, bufnr('$')), 'buflisted(v:val) && empty(bufname(v:val)) && bufwinnr(v:val) > 0') 338 | if !empty(emtpyBufs) 339 | silent execute 'bw' . a:bang . ' ' . join(emtpyBufs, ' ') 340 | return 1 341 | endif 342 | 343 | return 0 344 | endfunction 345 | 346 | 347 | function! smartq#smartq(bang, buffer, save) abort 348 | " Exit if filetype excluded 349 | if s:is_buf_excl() 350 | return 351 | elseif s:is_floating(0) && !s:is_zenmode_active() " Neovim only 352 | silent execute 'q' 353 | return 354 | endif 355 | 356 | let bufNr = s:str_to_bufnr(a:buffer) 357 | let bufName = bufname(bufNr) 358 | let curTabNr = tabpagenr() 359 | 360 | let bang = &buftype ==# 'terminal' ? '!' : a:bang 361 | 362 | " Save before quit 363 | if &modifiable && getbufvar(bufNr, '&modified') == 1 364 | if a:save ==# v:true 365 | let save = s:save_buf(a:bang, bufName) 366 | if save ==# 1 367 | return 368 | elseif save ==# 2 369 | if s:confirm_prompt('Buffer could not be saved, proceed quit?') 370 | let bang = '!' 371 | else 372 | return 373 | endif 374 | endif 375 | elseif &confirm ==# 0 && empty(a:bang) 376 | call s:echo_error('Changes detected. Please save your file(s) (add ! to override)', 0) 377 | return 378 | endif 379 | endif 380 | 381 | " Plugin Integrations 382 | if g:smartq_zenmode_integration && s:is_zenmode_active() 383 | call s:del_zenmode_buf(bang) 384 | return 385 | elseif g:smartq_goyo_integration && s:is_goyo_active() 386 | call s:del_goyo_buf(bang) 387 | return 388 | endif 389 | 390 | let modSplitsCount = s:count_mod_splits() " WARNING: toggles-off ZenMode 391 | let bufCount = len(getbufinfo({'buflisted':1})) 392 | 393 | " Built-ins 394 | if &diff 395 | call s:close_diff_bufs(bang) 396 | elseif s:is_buf_q() 397 | silent execute 'q' . bang 398 | elseif modSplitsCount ># 1 && bufCount ==# 1 && bufName ==# '' 399 | if !smartq#close_mod_splits(bang) 400 | if g:smartq_no_exit ==# 0 401 | silent execute 'qa' . bang 402 | else 403 | call s:echo_msg('Exit prevented. Only one buffer left.', 0) 404 | endif 405 | endif 406 | elseif modSplitsCount ==# 1 && bufCount ==# 1 && bufName ==# '' 407 | if g:smartq_no_exit ==# 0 || bang ==# '!' 408 | silent execute 'qa' . bang 409 | else 410 | call s:echo_msg('Exit prevented. Only one buffer left.', 0) 411 | endif 412 | elseif s:is_buf_bw() 413 | call s:del_buf(bufNr, 'bw', bang) 414 | else 415 | call s:del_buf(bufNr, 'bd', bang) 416 | endif 417 | 418 | return 419 | endfunction 420 | 421 | let &cpo = s:save_cpo 422 | unlet s:save_cpo 423 | 424 | -------------------------------------------------------------------------------- /init.vim: -------------------------------------------------------------------------------- 1 | execute 'source' fnamemodify(expand(''), ':h').'/plugin/smartq.vim' 2 | execute 'source' fnamemodify(expand(''), ':h').'/autoload/smartq.vim' 3 | 4 | -------------------------------------------------------------------------------- /plugin/smartq.vim: -------------------------------------------------------------------------------- 1 | " smartq.vim 2 | " Version: 1.4 3 | " 4 | " Author: 5 | " Mark Lucernas 6 | " Date: 7 | " 2021-06-12 8 | " Licence: 9 | " MIT 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | " Global variables 15 | if !exists('g:smartq_exclude_filetypes') 16 | let g:smartq_exclude_filetypes = [ 17 | \ 'fugitive' 18 | \ ] 19 | endif 20 | 21 | if !exists('g:smartq_exclude_buftypes') 22 | let g:smartq_exclude_buftypes= [ 23 | \ '' 24 | \ ] 25 | endif 26 | 27 | if !exists('g:smartq_q_filetypes') 28 | let g:smartq_q_filetypes = [ 29 | \ 'diff', 'git', 'gina-status', 'gina-commit', 'snippets', 30 | \ 'floaterm' 31 | \ ] 32 | endif 33 | 34 | if !exists('g:smartq_q_buftypes') 35 | let g:smartq_q_buftypes = [ 36 | \ 'quickfix', 'nofile' 37 | \ ] 38 | endif 39 | 40 | if !exists('g:smartq_bw_filetypes') 41 | let g:smartq_bw_filetypes = [ 42 | \ '' 43 | \ ] 44 | endif 45 | 46 | if !exists('g:smartq_bw_buftypes') 47 | let g:smartq_bw_buftypes = [ 48 | \ '' 49 | \ ] 50 | endif 51 | 52 | if !exists('g:smartq_auto_wipe_emtpy') 53 | let g:smartq_auto_wipe_emtpy = 1 54 | endif 55 | 56 | if !exists('g:smartq_no_exit') 57 | let g:smartq_no_exit = 0 58 | endif 59 | 60 | if !exists('g:smartq_auto_close_splits') 61 | let g:smartq_auto_close_splits = 0 62 | endif 63 | 64 | if !exists('g:smartq_goyo_integration') 65 | let g:smartq_goyo_integration = 1 66 | endif 67 | 68 | if !exists('g:smartq_zenmode_integration') 69 | let g:smartq_zenmode_integration = 1 70 | endif 71 | 72 | " SmartQ commands 73 | if !exists(':SmartQ') 74 | command! -bang -complete=buffer -nargs=? SmartQ 75 | \ call smartq#smartq(, , v:false) 76 | endif 77 | 78 | if !exists(':SmartQSave') 79 | command! -bang -complete=buffer -nargs=? SmartQSave 80 | \ call smartq#smartq(, , v:true) 81 | endif 82 | 83 | if !exists('SmartQWipeEmpty') 84 | command! -bang -nargs=0 SmartQWipeEmpty 85 | \ call smartq#wipe_empty_bufs() 86 | endif 87 | 88 | if !exists('SmartQCloseSplits') 89 | command! -nargs=0 SmartQCloseSplits call smartq#close_mod_splits('!') 90 | endif 91 | 92 | 93 | " Default mappings 94 | nnoremap (smartq_this) :SmartQ 95 | nnoremap (smartq_this_save) :SmartQSave 96 | nnoremap (smartq_this_force) :SmartQ! 97 | nnoremap (smartq_wipe_empty) :SmartQWipeEmpty 98 | nnoremap (smartq_wipe_empty_force) :SmartQWipeEmpty! 99 | nnoremap (smartq_close_splits) :SmartQCloseSplits 100 | 101 | if get(g:, 'smartq_default_mappings', 1) ==# 1 102 | " Remap macro record to Q 103 | nnoremap Q q 104 | nmap q (smartq_this) 105 | nmap (smartq_this_force) 106 | endif 107 | 108 | let &cpo = s:save_cpo 109 | unlet s:save_cpo 110 | --------------------------------------------------------------------------------