vim split if the buffer not empty - vim

I try create a map for open ~/.vimrc, but open the ~/.vimrc only when the buffer is empty, else split and open.
I try this
fun! BufferIsEmpty() "{{{
if line('$') == 1 && getline(1) == ''
return 1
else
return 0
endif
endf "}}}
fun! NotEmptySplit() "{{{
if !BufferIsEmpty()
sp
endif
return
endf
command! -nargs=0 NotEmptySplit call NotEmptySplit()
nnoremap <silent><leader>ve :NotEmptySplit <bar> ~/.vimrc<CR>
but I get this error
E488: Trailing characters

To take kev's excellent answer a bit further:
How about pulling out a generic 'open file in split if buffer not empty' function.
fu! OpenInSplitIfBufferDirty(file)
if line('$') == 1 && getline(1) == ''
exec 'e' a:file
else
exec 'sp' a:file
endif
endfu
nnoremap <silent> <leader>ve :call OpenInSplitIfBufferDirty($MYVIMRC)<cr>
command -nargs=1 -complete=file -bar CleverOpen :call OpenInSplitIfBufferDirty(<q-args>)

Adding -bar option will fix the E488 error.
command! -bar -nargs=0 NotEmptySplit call NotEmptySplit()
nnoremap <silent><leader>ve :NotEmptySplit <BAR> ~/.vimrc<CR>
But it will raise another E488 error from <BAR> ~/.vimrc<CR>.
I'm trying to refactor your code:
fun! OpenVimrc()
if line('$') == 1 && getline(1) == ''
e $MYVIMRC
else
sp $MYVIMRC
endif
endf
nnoremap <silent><leader>ve :call OpenVimrc()<CR>
These is a variable called b:changedtick to track changing counter.

Related

why it raise error `E523: Not allow here` in the simple function?

why it raise error E523: Not allow here in the simple function?
function! CheckMode()
echom mode()
exec "normal \<Esc>"
" normal ^[
" call feedkeys('\<esc>')
endfunction
inoremap <expr> <Esc> CheckMode()
In fact, what I want to do is:
memory the "insert mode" and auto start insert after come back. For example:
function! LeaveBuffer(key)
let b:is_insert_mode = mode() == 'i'
if b:is_insert_mode
exec "normal! \<C-\\>\<C-n>"
endif
exec "normal! \<C-w>".a:key
endfunction
noremap <expr> <C-w>h LeaveBuffer("h")
noremap <expr> <C-w>j LeaveBuffer("j")
noremap <expr> <C-w>k LeaveBuffer("k")
noremap <expr> <C-w>l LeaveBuffer("l")
function! EnterBuffer()
if b:is_insert_mode
startinsert
endif
endfunction
autocmd BufEnter,TermOpen term://** call EnterBuffer()

How to retain cursor position when using :%!filtercmd in vim?

When I issue a vim command that starts with :%!, such as :%!sort to sort all lines in the buffer, the cursor moves to the first line. How do I preserve the cursor position?
Ultimately, I want to use this command in an autocmd, such as:
augroup filetype_xxx
autocmd!
autocmd BufWrite *.xxx :%!sort
augroup END
Will the same method work in both places?
You can use a mark to remember the current line number (but note that the line contents could change):
augroup filetype_xxx
autocmd!
autocmd BufWrite *.xxx :kk
autocmd BufWrite *.xxx :%!sort
autocmd BufWrite *.xxx :'k
augroup END
I would rather use the Preserve function. Beyond solving your problem in this particular task you can use it for much more.
" preserve function
if !exists('*Preserve')
function! Preserve(command)
try
let l:win_view = winsaveview()
"silent! keepjumps keeppatterns execute a:command
silent! execute 'keeppatterns keepjumps ' . a:command
finally
call winrestview(l:win_view)
endtry
endfunction
endif
augroup filetype_xxx
autocmd!
autocmd BufWrite *.xxx :call Preserve("%!sort")
augroup END
You can also use the "Preserve Function" to perform other useful tasks like:
command! -nargs=0 Reindent :call Preserve('exec "normal! gg=G"')
DelBlankLines')
fun! DelBlankLines() range
if !&binary && &filetype != 'diff'
call Preserve(':%s/\s\+$//e')
call Preserve(':%s/^\n\{2,}/\r/ge')
endif
endfun
endif
command! -nargs=0 DelBlank :call DelBlankLines()
nnoremap <Leader>d :call DelBlankLines()<cr>
" remove trailing spaces
if !exists('*StripTrailingWhitespace')
function! StripTrailingWhitespace()
if !&binary && &filetype != 'diff'
call Preserve(":%s,\\s\\+$,,e")
endif
endfunction
endif
command! Cls call StripTrailingWhitespace()
cnoreabbrev cls Cls
cnoreabbrev StripTrailingSpace Cls

load external command in the same split after repeating it

I want to load some text coming from a command line command into a new vim split. I got this working but if I run the command again it keeps opening new splits.
What I want to achieve is getting this into the same split. How can I do this?
nnoremap <leader>q :execute 'new <bar> 0read ! bq query --dry_run --use_legacy_sql=false < ' expand('%')<cr>
I would suggest using the preview window via the :pedit command.
nnoremap <leader>q :execute 'pedit <bar> wincmd p <bar> 0read ! bq query --dry_run --use_legacy_sql=false < ' expand('%')<cr>
However we can do even better by doing the following:
Making a "query" operator using g# and 'opfunc'
A query command (feels very vim-like to do so)
Using stdin instead of a filename
Example:
function! s:query(str)
pedit [query]
wincmd p
setlocal buftype=nofile
setlocal bufhidden=wipe
setlocal noswapfile
%delete _
call setline(1, systemlist('awk 1', a:str))
endfunction
function! s:query_op(type, ...)
let selection = &selection
let &selection = 'inclusive'
let reg = ##
if a:0
normal! gvy
elseif a:type == 'line'
normal! '[V']y
else
normal! `[v`]y
endif
call s:query(##)
let &selection = selection
let ## = reg
endfunction
command! -range=% Query call s:query(join(getline(<line1>, <line2>), "\n"))
nnoremap \qq :.,.+<c-r>=v:count<cr>Query<cr>
nnoremap \q :set opfunc=<SID>query_op<cr>g#
xnoremap \q :<c-u>call <SID>query_op(visualmode(), 1)<cr>
Note: I am using awk 1 as my "query" command. Change to meet your needs.
For more help see:
:h :pedit
:h :windcmd
:h operator
:h g#
:h 'opfunc'
:h systemlist()

How to run go lang code directly from vim?

How to run go lang code directly from vim editor ?
e.g. currently edited file is array.go.
What kind of commands should I use to run this code in vim?
ok so after some trials this works: !go run %
Assuming that you've set environment variables properly; you can use this _gvimrc file (on Windows, it should be at C:\Users\UserName; on Linux, I do not know):
set guifont=Lucida_Console:h11
colorscheme dejavu
set tabstop=4
filetype plugin on
filetype plugin indent on
syntax on
" causes vim opens maximized in windows (#least)
au GUIEnter * simalt ~x
set autochdir
set number
set nobackup
" set nowritebackup
" this made my vim life (as a begginer at least) much happier!
" thanks to # http://vim.wikia.com/wiki/Display_output_of_shell_commands_in_new_window bottom of the page
function! s:ExecuteInShell(command, bang)
let _ = a:bang != '' ? s:_ : a:command == '' ? '' : join(map(split(a:command), 'expand(v:val)'))
if (_ != '')
let s:_ = _
let bufnr = bufnr('%')
let winnr = bufwinnr('^' . _ . '$')
silent! execute winnr < 0 ? 'belowright new ' . fnameescape(_) : winnr . 'wincmd w'
setlocal buftype=nowrite bufhidden=wipe nobuflisted noswapfile wrap number
silent! :%d
let message = 'Execute ' . _ . '...'
call append(0, message)
echo message
silent! 2d | resize 1 | redraw
silent! execute 'silent! %!'. _
silent! execute 'resize ' . line('$')
silent! execute 'syntax on'
silent! execute 'autocmd BufUnload <buffer> execute bufwinnr(' . bufnr . ') . ''wincmd w'''
silent! execute 'autocmd BufEnter <buffer> execute ''resize '' . line(''$'')'
silent! execute 'nnoremap <silent> <buffer> <CR> :call <SID>ExecuteInShell(''' . _ . ''', '''')<CR>'
silent! execute 'nnoremap <silent> <buffer> <LocalLeader>r :call <SID>ExecuteInShell(''' . _ . ''', '''')<CR>'
silent! execute 'nnoremap <silent> <buffer> <LocalLeader>g :execute bufwinnr(' . bufnr . ') . ''wincmd w''<CR>'
nnoremap <silent> <buffer> <C-W>_ :execute 'resize ' . line('$')<CR>
silent! syntax on
endif
endfunction
command! -complete=shellcmd -nargs=* -bang Shell call s:ExecuteInShell(<q-args>, '<bang>')
cabbrev shell Shell
" my additional tools
command! -complete=shellcmd -nargs=* -bang Gor call s:ExecuteInShell('go run %', '<bang>')
command! -complete=shellcmd -nargs=* -bang Gon call s:ExecuteInShell('go install', '<bang>')
command! -complete=shellcmd -nargs=* -bang Gob call s:ExecuteInShell('go build', '<bang>')
command! -complete=shellcmd -nargs=* -bang Got call s:ExecuteInShell('go test -v', '<bang>')
:map <F5> :Gor<CR>
:map <F6> :Gob<CR>
:map <F7> :Gon<CR>
:map <F9> :Got<CR>
:map <F10> :Fmt<CR>:w<CR>
:map <F12> :q<CR>
cabbrev fmt Fmt
:set encoding=utf-8
:set fileencodings=utf-8
Now when you press F5 it will run go (go run file.go) and shows the output in another document (you can :q to close the other document). Other commands are: F6 build, F7 install, F9 test and (my beloved one) F10 is fmt+:w.
BTW dejavu is my favorite color-scheme (code is from gorilla/mux):
You can also map a key in your ~/.vimrc as this
nnoremap gr :!go run %<CR>
So you can easily type gr in your vim and it will execute.
add the following two lines to your vimrc.
autocmd FileType go map <buffer> <F9> :w<CR>:exec '!go run' shellescape(#%, 1)<CR>
autocmd FileType go imap <buffer> <F9> <esc>:w<CR>:exec '!go run' shellescape(#%, 1)<CR>
this is inspired by an answer to a similar python question

NerdTree - Reveal file in tree

Is there a shortcut which reveal the current file in the NerdTree directory panel.
Like TextMate 'Reveal file in Drawer' - Ctrl+Command+R
in :h NERDTree:
:NERDTreeFind :NERDTreeFind
Find the current file in the tree. If no tree exists for the current tab,
or the file is not under the current root, then initialize a new tree where
the root is the directory of the current file.
I don't think it's bound to anything by default, so you have to do a keybind yourself.
nmap ,n :NERDTreeFind<CR>
is what appears in my .vimrc, along with
nmap ,m :NERDTreeToggle<CR>
Check this out, it automates the sync operation, whenever you change buffer, the nerdtree will automatically refreshed itself (I copied from here with tiny modifications)
" Check if NERDTree is open or active
function! IsNERDTreeOpen()
return exists("t:NERDTreeBufName") && (bufwinnr(t:NERDTreeBufName) != -1)
endfunction
" Call NERDTreeFind iff NERDTree is active, current window contains a modifiable
" file, and we're not in vimdiff
function! SyncTree()
if &modifiable && IsNERDTreeOpen() && strlen(expand('%')) > 0 && !&diff
NERDTreeFind
wincmd p
endif
endfunction
" Highlight currently open buffer in NERDTree
autocmd BufEnter * call SyncTree()
This should also probably be just a comment. With the current version toggling NerdTree and using SyncTree causes NERDTree to be invoked twice. This modification seems to fix that problem:
" Check if NERDTree is open or active
function! IsNERDTreeOpen()
return exists("t:NERDTreeBufName") && (bufwinnr(t:NERDTreeBufName) != -1)
endfunction
" Call NERDTreeFind iff NERDTree is active, current window contains a modifiable
" file, and we're not in vimdiff
function! SyncTree()
if &modifiable && IsNERDTreeOpen() && strlen(expand('%')) > 0 && !&diff
NERDTreeFind
wincmd p
endif
endfunction
" Highlight currently open buffer in NERDTree
autocmd BufEnter * call SyncTree()
function! ToggleNerdTree()
set eventignore=BufEnter
NERDTreeToggle
set eventignore=
endfunction
nmap <C-n> :call ToggleNerdTree()<CR>
Chen Rushan's answer + the comment worked perfectly well for me, except when the tree is open. With this setting, the current file in the tree will be revealed when the tree is opened.
" Check if NERDTree is open or active
function! IsNERDTreeOpen()
return exists("t:NERDTreeBufName") && (bufwinnr(t:NERDTreeBufName) != -1)
endfunction
function! CheckIfCurrentBufferIsFile()
return strlen(expand('%')) > 0
endfunction
" Call NERDTreeFind iff NERDTree is active, current window contains a modifiable
" file, and we're not in vimdiff
function! SyncTree()
if &modifiable && IsNERDTreeOpen() && CheckIfCurrentBufferIsFile() && !&diff
NERDTreeFind
wincmd p
endif
endfunction
" Highlight currently open buffer in NERDTree
autocmd BufRead * call SyncTree()
function! ToggleTree()
if CheckIfCurrentBufferIsFile()
if IsNERDTreeOpen()
NERDTreeClose
else
NERDTreeFind
endif
else
NERDTree
endif
endfunction
" open NERDTree with ctrl + n
nmap <C-n> :call ToggleTree()<CR>
To go along with Chen Rushan's post, the
autocmd BufEnter * call SyncTree()
won't let NERDTree close. I couldn't find a solution (other than below) that would highlight the current open buffer in NERDTree while allowing NERDTree to Toggle.
Below is what I scraped together to be able to toggle NERDTree and have files highlighted while using Ctrl + ] for my next buffer mapping.
Hopefully others can improve this.
"Buffers
set hidden
function! IsNERDTreeOpen()
return exists("t:NERDTreeBufName") && (bufwinnr(t:NERDTreeBufName) != -1)
endfunction
function! NextBuffer()
bnext
if IsNERDTreeOpen()
NERDTreeFind
wincmd p
endif
endfunction
nnoremap <c-]> <Esc>:call NextBuffer()<CR>
function! PrevBuffer()
bprev
if IsNERDTreeOpen()
NERDTreeFind
wincmd p
endif
endfunction
nnoremap <c-[> <Esc>:call PrevBuffer()<CR>
function! ToggleNT()
NERDTreeToggle
endfunction
map <c-u> <Esc>:call ToggleNT()<cr>
function! NerdTreeToggleFind()
if exists("g:NERDTree") && g:NERDTree.IsOpen()
NERDTreeClose
elseif filereadable(expand('%'))
NERDTreeFind
else
NERDTree
endif
endfunction
nnoremap <C-n> :call NerdTreeToggleFind()<CR>

Resources