So, I've added this function to my gvimrc, trying to get MacVim to re-open the same windows / same files, when rebooting.
" http://stackoverflow.com/questions/7955232/making-macvim-reopen-with-files-open-when-closed
" save and close all files and save global session
nnoremap <leader>q :mksession! ~/.vim/gvim-session.vim<CR>:wqa<CR>
" close all files without saving and save global session
nnoremap <leader>www :mksession! ~/.vim/gvim-session.vim<CR>:qa!<CR>
function! RestoreSession()
if argc() == 0 " vim called without arguments
let sessionFile='source ~/.vim/gvim-session.vim'
execute sessionFile
:call delete(sessionFile)
end
endfunction
autocmd VimEnter * call RestoreSession()
However, now, when I open MacVim, I get a completely blank window (that is, not even the ~~~s denoting blank lines, nor a status-bar or sign column or anything else) until I hit the return key:
I'm not sure what I'm doing wrong in my function to cause that. Any help?
You can and should drop the initial : in
:call delete(sessionFile)
delete() deletes a file but sessionFile doesn't point to a file:
let sessionFile='source ~/.vim/gvim-session.vim'
It should look like that:
let sessionFile='~/.vim/gvim-session.vim'
Why did you put source in the file path anyway? You could simply do the following:
execute "source " . sessionFile
Related
I have the following simple script. Where I want to find a tag, and if multiple options are available, let me choose the correct version. If the file does not exist, I want to sync it (retrieve the file from a repository) and then go there.
I tried this as a test:
function! GoToTag ()
try
normal! g]
catch
"" sync out the file and try going there again ""
echo v:exception
endtry
endfunction
nnoremap <F7> :call GoToTag()<CR>
But I kept getting "Press ENTER or type command to continue" which blocks the user from responding to "Type number and <Enter> (empty cancels):".
How do I get past this?
My fix for the "Press Enter" issue was to use exe 'tjump' instead of normal! g].
The rest of my solution is here in case others ever want to do the same thing:
function! GoToTag ()
try
let l:search_tag = expand('<cword>') " Get the word under the cursor
exe 'tjump' l:search_tag " go to tag, list options if tag is in multiple locations
catch /^Vim(tjump):E429:/ " catch the missing file error if file doesn't exist (not synced)
let l:exc = split(v:exception) " Split the error message
let l:filename = l:exc[2][1:-2] " Extract the filename from the error message ([2]) and get rid of quotes ([1:-2])
exe '!p4 sync' l:filename " Sync the file
call GoToTag() " Go to file again
endtry
endfunction
nnoremap <F7> :call GoToTag()<CR>
Try normal ^[ (insert the special character with Ctrl-V) or execute "normal \<c-[>".
You could also use built-in functions to get the tag under the cursor, find the corresponding file (see taglist), retrieve it if necessary, and jump to the tag without further user interaction.
I was trying to experiment on auto-load files which vim load at the time of start.
I kept the example.vim file in:
~/.vim/autoload/
directory and written a very simple function as:
echom "Autoloading..."
function! cpp#running#CompileAndRunFile(commands)
silent !clear
execute "!" . a:commands . " " . bufname("%")
endfunction
function! cpp#running#DebuggersOptions()
" Get the bytecode.
let bytecode = system(a:command . " -E -o " . bufname("%"))
" Open a new split and set it up.
vsplit __Bytecode__
normal! ggdG
setlocal filetype=potionbytecode
setlocal buftype=nofile
" Insert the bytecode.
call append(0, split(bytecode, '\v\n'))
endfunction
But I want to programatically force a reload of an autoload example.vim file which Vim has already loaded, without bothering the user. The reason being that I want that programmer at run-time can change behavior of the function and load latest modified function.
How can I do that ?
Thanks.
auto-load files which vim load at the time of start.
No. The autoload feature is exactly the opposite: an autoloaded script is sourced at runtime, when a function it contains is called.
But I want to programatically force a reload of an autoload example.vim file which Vim has already loaded, without bothering the user.
:source it again?
Let me jump right in.
What I'm trying to do is simply print out the file path of any open buffer when I exit vim. This is useful because I often open other files in vim buffers with a vim script I wrote that can search through my codebase for a specific function call.
I figure I can set up an autocommand, either for when I open a file or when I leave vim, and use the output from :ls to list all currently open buffers. The problem that I'm having is that I can't get any output to show up in terminal. I have tried various combinations of :!echo in my function, but to no avail. I have been trying something like the following in my .vimrc
function! PrintFileName()
:!echo "hello"
:exec "!echo world"
"... etc
endfunction
au BufRead * call PrintFileName()
Both :!echo foobar and :call PrintFileName() work for me if I do it from the command line. I also figure I might have to use some form of silent/redraw! so I don't have to hit enter to continue.
Really the main problem here is that I can't see a way to get output to stdout from inside my function and called by an autocommand.
Thanks for any help.
Okay, so I've found this solution, which works as long as I enter vim from the last line of my terminal. Otherwise this prints out a line below the current line and will get overwritten when you press enter. If anyone knows how to fix that let me know, otherwise I will use this.
function! PrintBuffers()
redir => files
:ls
redir END
" Regex to strip out everything from :ls but the buffer filenames
let files = substitute(files, '^[^"]*"', '', 'g')
let files = substitute(files, '"[^"]*\n[^"]*"', '\n', 'g')
let files = substitute(files, '"[^"]*$','','g')
" This is the magic line
exe '!echo; echo ' . shellescape(&t_te . files)
endfunction
au VimLeave * call PrintBuffers()
*Note - As I'm writing this, I realize that this won't display the right path if you did a :cd at some point. So I guess its pretty fragile, but it does the job.
Go (Golang) programming language comes with a tool called go fmt. Its a code formatter, which formats your code automagically (alignments, alphabetic sorting, tabbing, spacing, idioms...). Its really awesome.
So I've found this little autocommand which utilizes it in Vim, each time buffer is saved to file.
au FileType go au BufWritePre <buffer> Fmt
Fmt is a function that comes with Go vim plugin.
This is really great, but it has 1 problem. Each time formatter writes to buffer, it creates a jump in undo/redo history. Which becomes very painful when trying to undo/redo changes, since every 2nd change is formatter (making cursor jump to line 1).
So I am wondering, is there any way to discard latest change from undo/redo history after triggering Fmt?
EDIT:
Ok, so far I have:
au FileType go au BufWritePre <buffer> undojoin | Fmt
But its not all good yet. According to :h undojoin, undojoin is not allowed after undo. And sure enough, it fires an error when I try to :w after an undo.
So how do I achieve something like this pseudo-code:
if lastAction != undo then
au FileType go au BufWritePre <buffer> undojoin | Fmt
end
If I get this last bit figured out, I think I have a solution.
I think this is almost there, accomplishes what you ask, but I see it's deleting one undo point (I think this is expected from undojoin):
function! GoFmt()
try
exe "undojoin"
exe "Fmt"
catch
endtry
endfunction
au FileType go au BufWritePre <buffer> call GoFmt()
EDIT
Based on MattyW answer I recalled another alternative:
au FileType go au BufWritePre <buffer> %!gofmt
:%!<some command> executes a shell command over the buffer, so I do it before writing it to file. But also, it's gonna put the cursor at top of file...
Here is my go at this. It seems to be working well both with read/write autocmds and bound to a key. It puts the cursor back
and doesn't include the top-of-file event in the undos.
function! GoFormatBuffer()
if &modifiable == 1
let l:curw=winsaveview()
let l:tmpname=tempname()
call writefile(getline(1,'$'), l:tmpname)
call system("gofmt " . l:tmpname ." > /dev/null 2>&1")
if v:shell_error == 0
try | silent undojoin | catch | endtry
silent %!gofmt -tabwidth=4
endif
call delete(l:tmpname)
call winrestview(l:curw)
endif
endfunction
I check modifiable because I use vim as my pager.
I attempted to use #pepper_chino's answer but ran into issues where if fmt errors then vim would undo the last change prior to running GoFmt. I worked around this in a long and slightly convoluted way:
" Fmt calls 'go fmt' to convert the file to go's format standards. This being
" run often makes the undo buffer long and difficult to use. This function
" wraps the Fmt function causing it to join the format with the last action.
" This has to have a try/catch since you can't undojoin if the previous
" command was itself an undo.
function! GoFmt()
" Save cursor/view info.
let view = winsaveview()
" Check if Fmt will succeed or not. If it will fail run again to populate location window. If it succeeds then we call it with an undojoin.
" Copy the file to a temp file and attempt to run gofmt on it
let TempFile = tempname()
let SaveModified = &modified
exe 'w ' . TempFile
let &modified = SaveModified
silent exe '! ' . g:gofmt_command . ' ' . TempFile
call delete(TempFile)
if v:shell_error
" Execute Fmt to populate the location window
silent Fmt
else
" Now that we know Fmt will succeed we can now run Fmt with its undo
" joined to the previous edit in the current buffer
try
silent undojoin | silent Fmt
catch
endtry
endif
" Restore the saved cursor/view info.
call winrestview(view)
endfunction
command! GoFmt call GoFmt()
I just have this in my .vimrc:
au BufWritePost *.go !gofmt -w %
Automatically runs gofmt on the file when I save. It doesn't actually reformat it in the buffer so it doesn't interrupt what I'm looking at, but it's correctly formatted on disk so all check ins are properly formatted. If you want to see the correctly formatted code looks like you can just do :e .
Doesn't do anything to my undo/redo history either
You can install the vim plugins from the default repository. Alternatively, a pathogen friendly mirror is here:
https://github.com/jnwhiteh/vim-golang
Then you can use the :Fmt command to safely do a go fmt!
I read this stack thread on how to save a mapping permanently in vim.
I went to /etc/vim/vimrc and added the :map ,k :!python % <enter> in the first line of the file. When I open a new python file with vim the command responds by showing :!python % <enter> at the bottom of the screen. But it doesn't execute automatically. How do I fix this command to execute 'enter' automatically?
i think you rather want to use a local version ~/.vimrc for local settings than editing global settings in the file /etc/vim/vimrc. There you can add:
let maplocalleader=","
map <localleader>k :!python %<cr>
i would advise to not use ^M as explained in ZyX comment to ghoti's answer see
Edit
ZyX' comment made me change the code above to
filetype plugin on
augroup ft_python
au!
au FileType python nnoremap ,k :!python %<cr>
augroup END
which keeps ,k from messing with other stuff
filetype plugin on says that we want to have things done if a file has a certain filetype - in our case python
augroup ft_python says i want to have a group of autocommands := "commands that are invoked when opening a file" with that group-name
au! removes all autocommands
au Filetype python declares an autocommand=au for all files of type python
augroup END leaves the group ft_python and goes back to general settings
so this makes it possible to have ,k act as 'compile' in python but when i accidentally press ,k in another file say a c-source code, it does nothing (or the things i told ,k to be for c-source code somewhere else in my .vimrc).
Put in a literal carriage return character instead - press Ctrl + V, then Enter when writing the map:
:map ,k :!python %^M
You'll see the carriage return shown as ^M after typing the sequence Ctrl + V, then press the enter key.
That Ctrl + V key tells vim to insert the next character that you type.
The answer I was looking for is to paste :map :!python % <enter> in ~/.vimrc