Appending a line at the end of a file - vim

Within VIM, I can execute Octave scripts via this mapping:
map <F6> :w<CR>:!run-octave -q % <CR>
However, as I recently discovered, Octave doesn't show any plots unless there is a "pause" command at the end of a script.
How can I map F6 so this pause command is added automatically each time I invoke the key?
Thanks.

This may not be the best way to handle running Octave scripts from Vim, see below for an alternative.
The requested solution
To accomplish what you want, define the following function somewhere:
function! RunOctave()
let save_cursor = getpos('.')
call append(line('$'), "pause")
write
execute "!run-octave -q " . expand('%')
$delete _
write
call setpos('.', save_cursor)
endfunction
And define a mapping to call it:
map <F6> :w<CR>:call RunOctave<CR>
A better approach
I started out by running Octave similar to the above, but as I tend to use slow computers this is not a good solution for me. I have instead configured Vim to remote-control an instance of Octave.
This can be done through a terminal multiplexer, similar to what I suggested for Matlab here, e.g.:
tmux new-session -s octave "octave -q"
For optimal flexibility, I want to be able to evaluate single lines in octave from Vim:
imap <buffer> <F1> <Esc>:!tmux send-keys -t octave "<C-r>=getline('.')<CR>"<C-r>=nr2char(13)<CR><CR>a
nmap <buffer> <F1> :!tmux send-keys -t octave "<C-r>=getline('.')<CR>"<C-r>=nr2char(13)<CR><CR>
Evaluate visual selections:
vmap <buffer> <F2> call ExecSelection()<CR><CR>
Which depends on the following function:
let s:octave_selection = '/var/tmp/vim_octave_selection.m'
function! ExecSelection()
if line(".") == line("'<'")
exec ".write! " . s:octave_selection
else
exec ".write! >> " . s:octave_selection
endif
if line(".") == line("'>")
exec "!tmux send-keys -t octave 'run " . s:octave_selection . "'" . nr2char(13)
endif
endfunction
And last, but not least, evaluate the whole file:
imap <buffer> <F3> <Esc>:!tmux send-keys -t octave "<C-r>=expand('%:t:r')<CR>"<C-r>=nr2char(13)<CR><CR>a
nmap <buffer> <F3> :!tmux send-keys -t octave "<C-r>=expand('%:t:r')<CR>"<C-r>=nr2char(13)<CR><CR>
This last mapping requires that the current working directory for the buffer is the same as that of the Octave script.

Related

Taglist does not get updated dynamically

I am a beginner with VIMscript. While coding, I need to update the tags and cscope database so I can jump and search newly added code (functions, macros etc.)
My .vimrc file has following code:
function UpdateTags()
silent! execute (":!rm -rf tags cscope.files cscope.out")
silent! execute (":!ctags -R . *.c *.h *.hpp *.cpp --tag-relative=yes ./ 2>/dev/null")
silent! execute (":!cscope -b -R") | redraw!
normal == :cs reset<CR><CR>
normal == :TlistUpdate<CR>
endfunction
nnoremap <silent> <C-k> :call UpdateTags()<CR>
I see that the tags and cscope.out file is updated. However, i am unable to resolve these few things:
The screen flickers twice (I have put redraw only once in the function)
The taglist does not get updated. If I execute :TlistUpdate command again manually, then I see the new tags.
Following code is working:
function UpdateTags()
call system ("rm -rf tags cscope.files cscope.out")
call system ("ctags -R . *.c *.h *.hpp *.cpp --tag-relative=yes ./ 2>/dev/null")
call system ("cscope -b -R")
silent cscope reset
TlistUpdate
endfunction
sytem()
Swap execute with system. This has two benefits:
The screen doesn't blink and need redrawing, because of how system works
You should be able to use silent instead of silent!—the latter hides any errors
Use Ex (colon) commands as commands
normal == how you pretend the user ran == from normal mode. (You can avoid maps using normal!.)
To run, e.g., :cscope reset or :TlistUpdate, you just run them:
function! UpdateTags() abort
" ...
cscope reset
TlistUpdate
" ...
endfunction

Vim: open a temporary buffer displaying executable's output

I have found the :cwindow command to be very useful and I was wondering if I could get similar functionality using the output of my compiled code. I'd the output of :!./a.out to appear in a "quickfix" style buffer.
I've also noticed that even after taking the standard steps to prevent the "Press Enter to continue" message, it still happens at least once on :make and :!./a.out - using :silent to suppress this causes my tmux to go completely blank. My current workaround involves a mapping with a lot of carriage returns, is there another way?
Sure, you can use vim's preview window with a short function to execute the command, try this in your .vimrc:
fun! Runcmd(cmd)
silent! exe "noautocmd botright pedit ".a:cmd
noautocmd wincmd P
set buftype=nofile
exe "noautocmd r! ".a:cmd
noautocmd wincmd p
endfun
com! -nargs=1 Runcmd :call Runcmd("<args>")
Then you can:
:Runcmd ls
And see the results of ls in your preview window
I found this:
" Shell ------------------------------------------------------------------- {{{
function! s:ExecuteInShell(command) " {{{
let command = join(map(split(a:command), 'expand(v:val)'))
let winnr = bufwinnr('^' . command . '$')
silent! execute winnr < 0 ? 'botright vnew ' . fnameescape(command) : winnr . 'wincmd w'
setlocal buftype=nowrite bufhidden=wipe nobuflisted noswapfile nowrap nonumber
echo 'Execute ' . command . '...'
silent! execute 'silent %!'. command
silent! redraw
silent! execute 'au BufUnload <buffer> execute bufwinnr(' . bufnr('#') . ') . ''wincmd w'''
silent! execute 'nnoremap <silent> <buffer> <LocalLeader>r :call <SID>ExecuteInShell(''' . command . ''')<CR>:AnsiEsc<CR>'
silent! execute 'nnoremap <silent> <buffer> q :q<CR>'
silent! execute 'AnsiEsc'
echo 'Shell command ' . command . ' executed.'
endfunction " }}}
command! -complete=shellcmd -nargs=+ Shell call s:ExecuteInShell(<q-args>)
nnoremap <leader>! :Shell
" }}}
in steve losh's .vimrc - see which I shamelessly copied.
I have just discovered the :read command, which puts the output of a shell command into a window.
I went looking for this because I often want to grep for a file in the current directory which contains a certain string (and then open it into my current VIM).
Here is a shortcut I have in my $MYVIMRC:
noremap <leader>g :new<CR>:read ! grep -rn "
With this, when I press \g I get a new buffer created in a split window and find
:read ! grep -rn "
sitting waiting for me in the command area. Now I just type my search string, close the double quotes and hit <Enter> and the buffer fills with the command output.
Once done, a simple
:bw!
in that new buffer will kill it.
First open a preview window, and set it to autoread a file:
:botr pedit +:setl\ autoread /tmp/out.log
Now just run your command, and send the output to the file.
:!date > /tmp/out.log 2>&1
The result of your command should appear in the preview window.
However, we are still getting the "Press ENTER" prompt. A simple way to avoid that is to make a mapping that presses Enter for us:
:nmap <Leader>r :exec '!date > /tmp/out.log 2>&1'<CR><CR><CR>
I thought only two <CR>s would be needed but then found myself needing three.

Changing the practice of quiting and opening vi (vim) editor?

One of the primary distinction betweeen vi (vim) and emacs, is emacs is designed and supposed to be run at times without quitting, where as given the quick load time of vim, it is easier to quit and start for editing tasks. I read that it has become a cultural difference between these two editor users.
I tend to think that keeping the editor running at all times, kind of helps in productivity as you know that, something is in progress and you need not start again. What is best tricks and plugins that you have found to run a single vim session and do all your tasks from there?
For e.g, I edit Python programs, then quit to run the appengine appcfg and go back. Sometimes quit current file to open another file. I have not yet gotten used to concept of buffers and tabs, but rather run vim in my screen sessions, if I want to edit multiple files.
So you're running one file Vim per screen session? That sounds pretty bad man. You don't really need any special plugins to use multiple files in Vim easily. Just do
:e /home/project/myfile.py
I have set autochdir in my .vimrc which automatically changes current working directory to whatever buffer is currently active. So once you have that file open you can just do
:e myfile2.py
:e myfile3.py
etc. BTW opening any files in Vim can be completed with tab completion so make sure you are doing that. Once you have a bunch of buffers open to switch between I just do
:b myfile1.py
which you can also use tab completion for you can just type :b 1 and hit tab and it will figure out you want myfile1.py open so it is super quick if you can remember the general file name and if there is more than one similar match it will give you a list that you can tab through. For that I would also advise taking a look at the wildmode and wildmenu settings to see what you prefer they will give you enhanced tab completion menus. If at any time you start getting lost with what buffers are open and what you want to look at you can just do
:ls
and it will show you everything open.
Also remember you can run external commands by preceding a command with !
:!ls
for example. Hope some of this helps or at least gets you looking in the right direction.
Everything the others said plus three:
With set hidden you can open a new buffer in place of the current one, even if it's not saved. You can open dozens of buffers like that, no need to close Vim! See :help windows or the Vim wiki.
Supposing Vim is compiled with the correct flag (+clientserver) you can have a single Vim running as a "server" (in a terminal window A) and open all your files in that single Vim (from terminal window B). It's done in two steps:
$ vim --servername WHATEVER to start Vim
$ vim --remote file.js to open a file
Your file is opened in Vim in terminal window A and you still have your prompt in terminal window B.
Don't touch tabs. They are terribly wrongly named and don't work like tabs at all.
You can even drop down to a shell using :sh, and then get back to Vim using exit in the shell. For editing multiple files in the same Vim, you can use :vsplit filename or :split filename (for vertical and horizontal splits), and then use Esc+Ctrl+w+arrow keys to navigate between the different splits. This way you don't need tabs. Works especially well if you're working with small pieces of code.
Just use the :! command to run stuff in a shell. It mixes great with :cd and % expansion
bash> vim path/to/ex.c
...
:cd %:h. " move to path/ex/
:!gcc -o %:r % && %:r " compile ex.c into ex and run it
You can also mix it with :read if you want to put the output of a command in the current buffer:
:read !ls " read in the names of all the files in the current directory
Here's good video tutorial that helps with workflow of how and why to use a single Vim session to manage all your edits:
http://www.derekwyatt.org/vim/vim-tutorial-videos/vim-intermediate-tutorial-videos/#onevim
If I'm running vim from console (which I do on linux because I use ssh exclusively), then I often use CTRL-z to suspend vim. Then do my shell stuff and fg to return to vim.
Using ctags in vim is incredibly useful -- help tags for more info.
I use a perforce plugin that is quite powerful: http://www.vim.org/scripts/script.php?script_id=240. The diff support is amazing because you can cycle through all opened files or look at file history and diff between 2 older versions. Try :PVDiff, :PFilelog and :POpened.
I define a lot of macros for things like search and buffer windows manipulation. I have some interesting macros/functions listed here that help me live in vim.
Clipboard:
let mapleader=","
" put from clipboard
nmap ,p "*p
" yank to clipboard
nmap ,y "*y
Tags:
" jump to tag in other window
map t :call TagJumpOtherWindow()<cr>
function! TagJumpOtherWindow()
let cw = expand("<cword>")
winc p
exec "tjump " . cw
let #/ = cw
normal z.
winc p
endfunction
Scratch:
let mapleader=","
nmap ,x0 :e e:/work/scratch0.txt<CR>
nmap ,x1 :e e:/work/scratch1.txt<CR>
nmap ,x2 :e e:/work/scratch2.txt<CR>
nmap ,x3 :e e:/work/scratch3.txt<CR>
nmap ,x4 :e e:/work/scratch4.txt<CR>
nmap ,x5 :e e:/work/scratch5.txt<CR>
nmap ,x6 :e e:/work/scratch6.txt<CR>
nmap ,x7 :e e:/work/scratch7.txt<CR>
nmap ,x8 :e e:/work/scratch8.txt<CR>
nmap ,x9 :e e:/work/scratch9.txt<CR>
IDE:
function! GetMsdevFile(line)
let mx = '^\s*\([a-zA-Z_/\.0-9:\- ]*\)'
let line = matchstr( a:line, mx )
let file = substitute( line, mx, '\1', '' )
let file = substitute( line, '\\', '/', '' )
return file
endfunction
function! GetMsdevLineNumber(line)
let mx = '^\s*\([a-zA-Z_/\.0-9:\- ]*\)(\(\d\+\))'
let line = matchstr( a:line, mx )
let linenumber = substitute( line, mx, '\2', '' )
return linenumber
endfunction
function! GetMsdevFile2(line)
let file = expand("%:p:h") . "/" . GetMsdevFile(a:line)
let file
return file
endfunction
function! GetMsdevFile2(line)
let file = expand("%:p:h") . "/../" . GetMsdevFile(a:line)
let file
return file
endfunction
function! GotoMsdevMake( thiswin, version )
exec "cd ".$DIRECTORY."\\.."
let l = getline(".")
if a:version==0
let file = GetMsdevFile(l)
let linenumber = GetMsdevLineNumber(l)
elseif a:version==1
let file = GetMsdevFile2(l)
let linenumber = GetMsdevLineNumber(l)
else
let file = GetMsdevFile3(l)
let linenumber = GetMsdevLineNumber(l)
endif
if a:thiswin==1
winc p
endif
exec "e +" . linenumber. " " . file
exec "cd -"
endfunction
function! GetGCCFile(line)
let mx = '^\([a-zA-Z_/\.0-9:\- ]*\):[0-9]\+: .*'
let line = matchstr( a:line, mx )
let file = substitute( line, mx, '\1', '' )
let file = substitute( file, '\\', '/', '' )
return file
endfunction
function! GetGCCLineNumber(line)
let mx = '^\([a-zA-Z_/\.0-9:\- ]*\):\([0-9]\+\):.*'
let line = matchstr( a:line, mx )
let linenumber = substitute( line, mx, '\2', '' )
return linenumber
endfunction
function! GotoGCCMake()
exec "cd ".$DIRECTORY."\\.."
let l = getline(".")
let file = GetGCCFile(l)
let linenumber = GetGCCLineNumber(l)
winc p
exec "e +" . linenumber. " " . file
exec "cd -"
endfunction
function! MakeOut( filename )
exec ":e " . a:filename
call MakeBuffer()
normal zz
endfunction
" use the current buffer into a Visual Studio build output buffer to jump to errors
function! MakeBuffer()
normal! gg
exec "/).*error\\|failed"
nnoremap <buffer> <cr> :call GotoMsdevMake(1, 0)<cr>
nnoremap <buffer> :call GotoMsdevMake(1, 1)<cr>
nnoremap <buffer> o :call GotoMsdevMake(1, 1)<cr>
" nnoremap <buffer> :call GotoMsdevMake(0, 0)<cr>
endfunction
" use the current buffer into a GCC build output buffer to jump to errors
function! MakeGCCErr()
normal! gg
exec "/: error:"
nnoremap <buffer> <cr> :call GotoGCCMake()<cr>
nnoremap <buffer> :call GotoGCCMake()<cr>
nnoremap <buffer> o :call GotoGCCMake()<cr>
endfunction
function! MakeGCCOut( filename )
exec ":e " . a:filename
call MakeGCCErr()
endfunction
nmap ,mr :call MakeOut( "e:/perforce/branch/obj/release/BuildLog.htm" )<cr>
nmap ,md :call MakeOut( "e:/perforce/branch/obj/debug/BuildLog.htm" )<cr>
nmap ,mm :call MakeBuffer()<CR>
nmap ,mq :call MakeGCCErr()<cr>
I keep a single vim window open for days at a time. split windows work really nicely on large screens.
I also like tabs; I cluster my splits for a single project in a tab, but keep other tabs around for my day plan, my vim wiki, scratch notes for when I'm interrupted. I find tabs easier to use than multiple windows.

Adding a command to Vim

I finally decided to try out Vim, as I am getting increasingly frustrated by GUI editors. So far, I'm loving it, but I can't find any help for a issue I'm having...
I am trying to map the command :Pyrun to :!python % in Vim using cmap. The mapping shows up fine if I type :cmap. However, on typing :Pyrun, I get this error message:
Not an editor command: Pyrun.
Here is what I'm trying in .vimrc:
:autocmd FileType python :cmap Pyrun<cr> !python %<cr>
:autocmd FileType python :cmap Intpyrun<cr> !python -i %<cr>
What can I do to solve this problem?
I would try something like this in your .vimrc or your ftplugin/python_ft.vim
command Pyrun execute "!python %"
command Intpyrun execute "!python -i %"
Then :Pyrun and :Intpyrun should work
You could then map a function key to each
map <F5> :Pyrun<CR>
map <F6> :Intpyrun<CR>
I personally prefer another approach. First create a function receiving the command arguments and then create a command to call the function:
fun! DoSomething( arg ) "{{{
echo a:arg
" Do something with your arg here
endfunction "}}}
command! -nargs=* Meh call DoSomething( '<args>' )
So it would be like
fun! Pyrun( arg ) "{{{
execute '!python ' . expand( '%' )
endfunction "}}}
command! -nargs=* Pyrun call Pyrun( '<args>' )
But, there's a better way to do it in Vim. Use makeprg:
makeprg=python\ %
Just type :make to run your current Python file. Use :copen to show error list.
G'day,
Similar to karoberts answer, I prefer the more direct:
:map <F9> :!python %<CR>
If my script is creating some output I also like to capture it in a temp file and then autoread that files content into another buffer, e.g.
:map <F9> :!python % 2>&1 \| tee /tmp/results
I then set autoread by entering :set autoread and opening the results file in another buffer
:split /tmp/results<CR>
Then I can easily see the results of the run in the buffer that auto refreshes when the results file is updated by running the script under development.
HTH
cheers,
With new LUA api:
vim.api.nvim_create_user_command('Hello', 'echo "Hello World!"', {})
vim.api.nvim_create_user_command('HelloLua', function ()
print('Hello LUA!')
end, {})
NeoVIM API reference

How to execute file I'm editing in Vi(m)

How to execute file that I'm editing in Vi(m) and get output in split window (like in SciTE)?
Of course I could execute it like that:
:!scriptname
But is it posible to avoid writing script name and how to get output in split window instead just bottom of the screen?
There is the make command. It runs the command set in the makeprg option. Use % as a placeholder for the current file name. For example, if you were editing a python script:
:set makeprg=python\ %
Yes, you need to escape the space. After this you can simply run:
:make
If you wish, you can set the autowrite option and it will save automatically before running the makeprg:
:set autowrite
This solves the execute part. Don't know any way of getting that output into a split window that doesn't involve redirection to file.
To access the current buffer's filename, use %. To get it into a variable you can use the expand() function. To open a new window with a new buffer, use :new or :vnew. To pipe the output from a command into the current buffer, use :.! . Putting it all together:
:let f=expand("%")|vnew|execute '.!ruby "' . f . '"'
obviously replacing ruby with whatever command you want. I used execute so I could surround the filename with quotation marks, so it'll work if the filename has spaces in it.
Vim has ! ("bang") command which executes shell command directly from VIM window. Moreover it allows launching sequence of commands that are connected with pipe and read stdout.
For example:
! node %
is equivalent to opening command prompt window and launching commands:
cd my_current_directory
node my_current_file
See "Vim tips: Working with external commands" for details.
I have a shortcut for that in my vimrc:
nmap <F6> :w<CR>:silent !chmod 755 %<CR>:silent !./% > .tmp.xyz<CR>
\ :tabnew<CR>:r .tmp.xyz<CR>:silent !rm .tmp.xyz<CR>:redraw!<CR>
This writes the current buffer, makes the current file executable (unix only), executes it (unix only) and redirects the output to .tmp.xyz, then creates a new tab, reads the file and then deletes it.
Breaking it down:
:w<CR> write current buffer
:silent !chmod 755 %<CR> make file executable
:silent !./% > .tmp.xyz<CR> execute file, redirect output
:tabnew<CR> new tab
:r .tmp.xyz<CR> read file in new tab
:silent !rm .tmp.xyz<CR> remove file
:redraw!<CR> in terminal mode, vim get scrambled
this fixes it
For Shell script I've used
:set makeprg=%
:make
Vim 8 has an interactive terminal built in. To run the current bash script in a split pane:
:terminal bash %
or for short
:ter bash %
% expands to the current file name.
From :help terminal:
The terminal feature is optional, use this to check if your Vim has it:
echo has('terminal')
If the result is "1" you have it.
I use a slightly more intrusive mechanism through maps:
map ;e :w<CR>:exe ":!python " . getreg("%") . "" <CR>
Just makes it so I don't have to save, then go. Just go.
You can use vim's plugin bexec. To my knowledge the latest version is 0.5.
Then:
$ mkdir -p ~/.vim/plugin
$ mv bexec-0.5.vba ~/.vim/plugin
$ vim ~/.vim/plugin/bexec-0.5.vba
Inside vim itself while editing the .vba file do:
:so %
Some output will show up letting you know that bexec.vim has been written as well as documentation, etc..
Now, you can test it by opening your (whatever language script that has an #! interpreter working properly) in vim and run
:Bexec
Note: I wanted the split to be vertical rather than horizontal, so I did:
$ grep -i -n split ~/.vim/plugin/bexec.vim | grep -i hor
102: let bexec_splitdir = "hor" " hor|ver
261: exec {"ver":"vsp", "hor":"sp"}[g:bexec_splitdir]
and changed the value of from "hor" to "ver"..
I know it's an old question, but I hope this can help someone out there. I have been running in the same issue while taking Coursera's Startup Engineering course where professor Palaji uses Emacs and I don't like Emacs..
Just use colon and exclamatory mark as shown below
:!< script_name>
Based on #SethKriticos and #Cyril answers I now use the following:
function! Setup_ExecNDisplay()
execute "w"
execute "silent !chmod +x %:p"
let n=expand('%:t')
execute "silent !%:p 2>&1 | tee ~/.vim/output_".n
" I prefer vsplit
"execute "split ~/.vim/output_".n
execute "vsplit ~/.vim/output_".n
execute "redraw!"
set autoread
endfunction
function! ExecNDisplay()
execute "w"
let n=expand('%:t')
execute "silent !%:p 2>&1 | tee ~/.vim/output_".n
" I use set autoread
"execute "1 . 'wincmd e'"
endfunction
:nmap <F9> :call Setup_ExecNDisplay()<CR>
:nmap <F2> :call ExecNDisplay()<CR>
Use F9 to setup the new window and F2 to execute your script and tee to your output file.
I also added the script name to the output file name, so that you can use this for multiple scripts at the same time.
In your .vimrc you can paste this function
function! s:ExecuteInShell(command)
let command = join(map(split(a:command), 'expand(v:val)'))
let winnr = bufwinnr('^' . command . '$')
silent! execute ':w'
silent! execute winnr < 0 ? 'vnew ' . fnameescape(command) : winnr . 'wincmd w'
setlocal buftype=nowrite bufhidden=wipe nobuflisted noswapfile nowrap number
silent! execute 'silent %!'. command
silent! redraw
silent! execute 'au BufUnload <buffer> execute bufwinnr(' . bufnr('#') . ') . ''wincmd w'''
silent! execute 'nnoremap <silent> <buffer> <LocalLeader>r :call <SID>ExecuteInShell(''' . command . ''')<CR>'
silent! execute 'wincmd w'
" echo 'Shell command ' . command . ' executed.'
endfunction
command! -complete=shellcmd -nargs=+ Shell call s:ExecuteInShell(<q-args>)
cabbrev shell Shell
After that, in vim run command :shell python ~/p.py as example. And you will get the output in splitted window.
+ After changes in p.py as example you will run the same command again, this function will not create new window again, it will display the result in the previous(same) splitted window.
#xorpaul
I was looking for this script (python/Windows) for quite some time. As there is no "tee" in Windows I changed it to:
function! Setup_ExecNDisplay()
execute "w"
let n=expand('%:t')
execute "silent ! python % > d:\\temp\\output_".n ." 2>&1"
execute "vsplit d:\\temp\\output_".n
execute "redraw!"
set autoread
endfunction
function! ExecNDisplay()
execute "w"
let n=expand('%:t')
execute "silent ! python % > d:\\temp\\output_".n . " 2>&1"
endfunction
:nmap <F9> :call Setup_ExecNDisplay()<CR>
:nmap <F2> :call ExecNDisplay()<CR>
I'd recommend the plugin quickrun. It's fast and simple to configure. Here's a little demonstration:

Resources