running python on vim - vim

Over on askubuntu.com I was told how to run python on Vim. I am testing the set up which works with the code 1st or 2nd code python code at using python to solve a non linear equation.
The only thing I have done different was added print(a) as the last line. I ran this yesterday from the shell and it worked perfectly. Could someone let me know what is going wrong?
Ok so I corrected the vimrc with the appropriate question marks,
chmod +x ~/path/to/file/hw6problem2.py
Then from vim I ran
:Shell ./#
but I received the same syntax error again. (Does the file have to be saved as .sh because I can't get any .py files to run?)
dustin#dustin:~$ vim /home/dustin/Documents/School/UVM/Engineering/OrbitalMechanics/hw6problem2.py
File "hw6problem2.py", line 14
a0 = max(s/2, (s - c)/2)
^
SyntaxError: invalid syntax
shell returned 1
Press ENTER or type command to continue
vimrc
syntax on
au BufWinLeave * mkview "records settings
au BufWinEnter * silent loadview "reloads settings
set nu "puts line numbers on
set ic "case insensitive
set foldmethod=syntax "for the latex-suite
set autoread "autoload when files in the buffer have been modified
set autochdir "autochange directory
"set wrap
set wrap
" set lines=50 columns=80
" resizes window
:map g1 :set lines=20<CR>:set columns=80<CR>
:map g2 :set lines=50<CR>:set columns=80<CR>
:map g3 :set lines=50<CR>:set columns=170<CR>
:map <F6> :! firefox % &<CR>
:map E Ea
"set autoindent
set tabstop=4
set shiftwidth=2
set expandtab
set smartindent
"
" Stuff for latex-suite
" REQUIRED. This makes vim invoke Latex-Suite when you open a tex file.
" It also allows you to set different actions for different filetypes
" in ~/.vim/after/ftplugin/*.vim
filetype plugin on
set shellslash
" IMPORTANT: grep will sometimes skip displaying the file name if you
" search in a singe file. This will confuse Latex-Suite. Set your grep
" program to always generate a file-name.
set grepprg=grep\ -nH\ $*
" OPTIONAL: This enables automatic indentation as you type.
filetype indent on
" OPTIONAL: Starting with Vim 7, the filetype of empty .tex files defaults to
" 'plaintex' instead of 'tex', which results in vim-latex not being loaded.
" The following changes the default filetype back to 'tex':
let g:tex_flavor='latex'
let g:Tex_ViewRule_pdf = 'okular'
"""""""""""""""""""""""""""""""""""""""
" => Shell command
"""""""""""""""""""""""""""""""""""""""
command! -complete=shellcmd -nargs=+ Shell call s:RunShellCommand(<q-args>)
function! s:RunShellCommand(cmdline)
let isfirst = 1
let words = []
for word in split(a:cmdline)
if isfirst
let isfirst = 0 " don't change first word (shell command)
else
if word[0] =~ '\v[%#<]'
let word = expand(word)
endif
let word = shellescape(word, 1)
endif
call add(words, word)
endfor
let expanded_cmdline = join(words)
rightbelow new
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
call setline(1, 'You entered: ' . a:cmdline)
call setline(2, 'Expanded to: ' . expanded_cmdline)
call append(line('$'), substitute(getline(2), '.', '=', 'g'))
silent execute '$read !'. expanded_cmdline
1
endfunction

This is likely to be a python issue.
On a side not, there's a great shell function for executing scripts and redirecting output to vim buffer (split window).
Syntax to execute current script (you should have chmod +x and shebang line):
:Shell ./#
In order to add the function, add this to .vimrc:
command! -complete=shellcmd -nargs=+ Shell call s:RunShellCommand(<q-args>)
function! s:RunShellCommand(cmdline)
let isfirst = 1
let words = []
for word in split(a:cmdline)
if isfirst
let isfirst = 0 " don't change first word (shell command)
else
if word[0] =~ '\v[%#<]'
let word = expand(word)
endif
let word = shellescape(word, 1)
endif
call add(words, word)
endfor
let expanded_cmdline = join(words)
rightbelow new
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
call setline(1, 'You entered: ' . a:cmdline)
call setline(2, 'Expanded to: ' . expanded_cmdline)
call append(line('$'), substitute(getline(2), '.', '=', 'g'))
silent execute '$read !'. expanded_cmdline
1
endfunction
https://github.com/ruslanosipov/dotfiles/blob/master/.vimrc#L137

Related

Echoing string and variable in vim script

Have the following simple function in a vim script:
function me#Tabwidth(width)
let &tabstop = a:width
let &shiftwidth = a:width
set expandtab
echom "Tab width set to " + a:width
endfunction
The function is being called like this in the vimrc file.
command -nargs=* Tabwidth :call me#Tabwidth(<f-args>)
When called by typing "Tabwidth 2" only the value of the variable is being echoed out, but not the string. What am I doing wrong?
In vim script, string concatenation is done with . operator. Try like this:
echom "Tab width set to " . a:width
If a:width is a number, it will be automatically converted.

A keybinding in vim has stopped and I'm stumped

I set up a key binding in my .vimrc to allow me to use silver-searcher for quick string searches across my apps.
Currently my .vimrc looks like this:
" .vimrc
set shell=/bin/sh
" load up pathogen and all bundles
call pathogen#infect()
call pathogen#helptags()
syntax on " show syntax highlighting
filetype plugin indent on
set autoindent " set auto indent
set ts=2 " set indent to 2 spaces
set shiftwidth=2
set expandtab " use spaces, not tab characters
set nocompatible " don't need to be compatible with old vim
set relativenumber " show relative line numbers
set showmatch " show bracket matches
set ignorecase " ignore case in search
set hlsearch " highlight all search matches
set cursorline " highlight current line
set smartcase " pay attention to case when caps are used
set incsearch " show search results as I type
set mouse=a " enable mouse support
set ttimeoutlen=100 " decrease timeout for faster insert with 'O'
set vb " enable visual bell (disable audio bell)
set ruler " show row and column in footer
set scrolloff=2 " minimum lines above/below cursor
set laststatus=2 " always show status bar
set list listchars=tab:»·,trail:· " show extra space characters
set nofoldenable " disable code folding
set clipboard=unnamed " use the system clipboard
set wildmenu " enable bash style tab completion
set wildmode=list:longest,full
runtime macros/matchit.vim " use % to jump between start/end of methods
" put git status, column/row number, total lines, and percentage in status
set statusline=%F%m%r%h%w\ %{fugitive#statusline()}\ [%l,%c]\ [%L,%p%%]
" set dark background and color scheme
set background=dark
colorscheme vimbrant
" set up some custom colors
highlight ColorColumn ctermbg=7
highlight ColorColumn guibg=Gray
" highlight the status bar when in insert mode
if version >= 700
au InsertEnter * hi StatusLine ctermfg=235 ctermbg=2
au InsertLeave * hi StatusLine ctermbg=240 ctermfg=12
endif
" highlight trailing spaces in annoying red
highlight ExtraWhitespace ctermbg=1 guibg=red
match ExtraWhitespace /\s\+$/
autocmd BufWinEnter * match ExtraWhitespace /\s\+$/
autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\#<!$/
autocmd InsertLeave * match ExtraWhitespace /\s\+$/
autocmd BufWinLeave * call clearmatches()
" set leader key to comma
let mapleader = ","
"silver searcher config
let g:ackprg = 'ag --nogroup --nocolor --column'
" ctrlp config
set runtimepath^=~/.vim/bundle/ctrlp.vim
let g:ctrlp_map = '<leader>f'
let g:ctrlp_max_height = 30
let g:ctrlp_working_path_mode = 0
let g:ctrlp_match_window_reversed = 0
" use silver searcher for ctrlp
let g:ctrlp_user_command = 'ag %s -l --nocolor -g ""'
" unmap F1 help
nmap <F1> :echo<CR>
imap <F1> <C-o>:echo<CR>
" map . in visual mode
vnoremap . :norm.<cr>
" die hash rockets, die!
vnoremap <leader>h :s/:\(\w*\) *=>/\1:/g<cr>
" map markdown preview
map <leader>m :!open -a Marked %<cr><cr>
" map git commands
map <leader>b :Gblame<cr>
map <leader>l :!clear && git log -p %<cr>
map <leader>d :!clear && git diff %<cr>
" open gist after it's been created
let g:gist_open_browser_after_post = 1
" map Silver Searcher
map <leader>a :Ag!<space>
" search for word under cursor with Silver Searcher
map <leader>A :Ag! "<C-r>=expand('<cword>')<CR>"
" clear the command line and search highlighting
noremap <C-l> :nohlsearch<CR>
" toggle spell check with <F5>
map <F5> :setlocal spell! spelllang=en_us<cr>
imap <F5> <ESC>:setlocal spell! spelllang=en_us<cr>
" add :Plain command for converting text to plaintext
command! Plain execute "%s/’/'/ge | %s/[“”]/\"/ge | %s/—/-/ge"
" hint to keep lines short
if exists('+colorcolumn')
set colorcolumn=80
endif
" execute current file
map <leader>e :call ExecuteFile(expand("%"))<cr>
" execute file if we know how
function! ExecuteFile(filename)
:w
:silent !clear
if match(a:filename, '\.rb$') != -1
exec ":!ruby " . a:filename
elseif match(a:filename, '\.js$') != -1
exec ":!node " . a:filename
elseif match(a:filename, '\.sh$') != -1
exec ":!bash " . a:filename
else
exec ":!echo \"Don't know how to execute: \"" . a:filename
end
endfunction
" jump to last position in file
autocmd BufReadPost *
\ if line("'\"") > 0 && line("'\"") <= line("$") |
\ exe "normal g`\"" |
\ endif
" multi-purpose tab key (auto-complete)
function! InsertTabWrapper()
let col = col('.') - 1
if !col || getline('.')[col - 1] !~ '\k'
return "\<tab>"
else
return "\<c-p>"
endif
endfunction
inoremap <tab> <c-r>=InsertTabWrapper()<cr>
inoremap <s-tab> <c-n>
" rename current file, via Gary Bernhardt
function! RenameFile()
let old_name = expand('%')
let new_name = input('New file name: ', expand('%'))
if new_name != '' && new_name != old_name
exec ':saveas ' . new_name
exec ':silent !rm ' . old_name
redraw!
endif
endfunction
map <leader>n :call RenameFile()<cr>
function! RunTests(filename)
" Write the file and run tests for the given filename
:w
:silent !clear
if match(a:filename, '\.feature$') != -1
exec ":!bundle exec cucumber " . a:filename
elseif match(a:filename, '_test\.rb$') != -1
if filereadable("bin/testrb")
exec ":!bin/testrb " . a:filename
else
exec ":!ruby -Itest " . a:filename
end
else
if filereadable("Gemfile")
exec ":!bundle exec rspec --color " . a:filename
else
exec ":!rspec --color " . a:filename
end
end
endfunction
function! SetTestFile()
" set the spec file that tests will be run for.
let t:grb_test_file=#%
endfunction
function! RunTestFile(...)
if a:0
let command_suffix = a:1
else
let command_suffix = ""
endif
" run the tests for the previously-marked file.
let in_test_file = match(expand("%"), '\(.feature\|_spec.rb\|_test.rb\)$') != -1
if in_test_file
call SetTestFile()
elseif !exists("t:grb_test_file")
return
end
call RunTests(t:grb_test_file . command_suffix)
endfunction
function! RunNearestTest()
let spec_line_number = line('.')
call RunTestFile(":" . spec_line_number . " -b")
endfunction
" run test runner
map <leader>t :call RunTestFile()<cr>
map <leader>T :call RunNearestTest()<cr>
" show hidden files in NERDTree
let NERDTreeShowHidden=1
" show hidden files with ctrlp
let g:ctrlp_show_hidden = 1
" Mapping ESC in insert mode and command mode to double i
imap ii <C-[>
cmap ii <C-[>
What's weird is when I hit ,A it works perfectly, but ,a runs my test suite which is currently mapped to ,t.
I've been looking at this for hours and I think I'm just missing something dumb. I'm currently using macvim 7.4.52.

Vim: inoremap works in buffer, not in .vimrc

I'm really eager to include the following in my .vimrc file:
inoremap <Tab> <C-x><C-u>
If I set it within a buffer (via :inoremap <Tab> <C-x><C-u>) it works exactly as I'd hoped.
But, if I place it in my .vimrc, it doesn't seem to be acknowledged at all.
I've attached my .vimrc below. A few things:
Other changes to the .vimrc file are picked up, so it's not the wrong file
Have tried adding at the very bottom of the .vimrc & still doesn't work, so it's not being overwritten
Any ideas appreciated. Many thanks.
" When started as "evim", evim.vim will already have done these settings.
if v:progname =~? "evim"
finish
endif
" Word complete
" :autocmd BufEnter * call DoWordComplete()
" let g:WC_min_len = 4
" Use Vim settings, rather than Vi settings (much better!).
" This must be first, because it changes other options as a side effect.
set nocompatible
map j gj
map k gk
set showmatch " Show matching brackets
set mat=5 " Bracket blinking
set noerrorbells " No noise
" Ruby autocomplete
" Autocomplete behaviour
set completeopt=longest,menuone
open omni completion menu closing previous if open and opening new menu without changing the text
inoremap <expr> <C-Space> (pumvisible() ? (col('.') > 1 ? '<Esc>i<Right>' : '<Esc>i') : '') .
\ '<C-x><C-o><C-r>=pumvisible() ? "\<lt>C-n>\<lt>C-p>\<lt>Down>" : ""<CR>'
" open user completion menu closing previous if open and opening new menu without changing the text
inoremap <expr> <S-Space> (pumvisible() ? (col('.') > 1 ? '<Esc>i<Right>' : '<Esc>i') : '') .
\ '<C-x><C-u><C-r>=pumvisible() ? "\<lt>C-n>\<lt>C-p>\<lt>Down>" : ""<CR>'
autocmd FileType ruby,eruby set omnifunc=rubycomplete#Complete
autocmd FileType ruby,eruby let g:rubycomplete_buffer_loading = 1
autocmd FileType ruby,eruby let g:rubycomplete_rails = 1
autocmd FileType ruby,eruby let g:rubycomplete_classes_in_global = 1
" highlight Pmenu ctermbg=238 gui=bold "improve autocomplete menu color
" Colours
highlight Pmenu ctermfg=6 ctermbg=238 guibg=grey30
" allow backspacing over everything in insert mode
set backspace=indent,eol,start
" if has("vms")
" set nobackup " do not keep a backup file, use versions instead
" else
" set backup " keep a backup file
" endif
" Set backupdir to tmp
" Do not let vim create <filename>~ backup files
set nobackup
" set nowritebackup
set history=50 " keep 50 lines of command line history
set ruler " show the cursor position all the time
set showcmd " display incomplete commands
set incsearch " do incremental searching
" Set tab to 2 spaces
set ts=2
set shiftwidth=2
" Ignore case
set ignorecase
set smartcase
" Menu autocomplete
set wildmode=longest,list
set wildmenu
" Call pathogen
call pathogen#infect()
" For Win32 GUI: remove 't' flag from 'guioptions': no tearoff menu entries
" let &guioptions = substitute(&guioptions, "t", "", "g")
" Don't use Ex mode, use Q for formatting
map Q gq
" CTRL-U in insert mode deletes a lot. Use CTRL-G u to first break undo,
" so that you can undo CTRL-U after inserting a line break.
inoremap <C-U> <C-G>u<C-U>
" In many terminal emulators the mouse works just fine, thus enable it.
if has('mouse')
set mouse=a
endif
" Switch syntax highlighting on, when the terminal has colors
" Also switch on highlighting the last used search pattern.
if &t_Co > 2 || has("gui_running")
syntax on
set hlsearch
endif
" Turn syntax highlighting on (Added by John Bayne, 18/08/2012)
syntax on
" Only do this part when compiled with support for autocommands.
if has("autocmd")
" Enable file type detection.
" Use the default filetype settings, so that mail gets 'tw' set to 72,
" 'cindent' is on in C files, etc.
" Also load indent files, to automatically do language-dependent indenting.
filetype plugin indent on
" Put these in an autocmd group, so that we can delete them easily.
augroup vimrcEx
au!
" For all text files set 'textwidth' to 78 characters.
autocmd FileType text setlocal textwidth=78
" When editing a file, always jump to the last known cursor position.
" Don't do it when the position is invalid or when inside an event handler
" (happens when dropping a file on gvim).
" Also don't do it when the mark is in the first line, that is the default
" position when opening a file.
autocmd BufReadPost *
\ if line("'\"") > 1 && line("'\"") <= line("$") |
\ exe "normal! g`\"" |
\ endif
augroup END
else
set autoindent " always set autoindenting on
endif " has("autocmd")
" Convenient command to see the difference between the current buffer and the
" file it was loaded from, thus the changes you made.
" Only define it when not defined already.
if !exists(":DiffOrig")
command DiffOrig vert new | set bt=nofile | r ++edit # | 0d_ | diffthis
\ | wincmd p | diffthis
endif
" My customisations
" No backup files
set nobackup
set nowritebackup
set noswapfile
" Whitespace identifier
:highlight ExtraWhitespace ctermbg=darkgreen guibg=lightgreen
:match ExtraWhitespace /\s\+$/
" Colour options
" color codeschool
" set guifont=Monaco:h12
" let g:NERDTreeWinPos = "right"
" set guioptions-=T " Removes top toolbar
" set guioptions-=r " Removes right hand scroll bar
" set go-=L " Removes left hand scroll bar
" autocmd User Rails let b:surround_{char2nr('-')} = "<% \r %>" " displays <% %> correctly
" :set cpoptions+=$ " puts a $ marker for the end of words/lines in cw/c$ commands
" Tab behaviour for ultisnips
let g:UltiSnipsExpandTrigger="<tab>"
let g:UltiSnipsJumpForwardTrigger="<tab>"
let g:UltiSnipsJumpBackwardTrigger="<s-tab>"
inoremap <Tab> <C-x><C-u>
In this case, :scriptnames, while useful, is not the best way to see where a mapping was last set.
:verbose map <tab>
is a lot more precise.
Maybe another script is overwriting it after your .vimrc is read.
You can use :scriptnames to see what files are read on startup.

Vim - show diff on commit in mercurial;

In my .hgrc I can provide an editor or a command to launch an editor with options on commit.
I want to write a method or alias that launches $ hg ci, it would not only open up message in Vim, but also would split window and there print out $ hg diff.
I know that I can give parameters to vim by using +{command} option. So launching $ vim "+vsplit" does the split but any other options goes to first opened window. So I assume i need a specific function, yet I have no experience in writing my own Vim scripts.
The script should:
Open new vertical split with empty buffer (with vnew possibly)
In empty buffer launch :.!hg diff
Set empty buffer file type as diff :set ft=diff
I've written such function:
function! HgCiDiff()
vnew
:.!hg diff
set ft=diff
endfunction
And in .hgrc I've added option: editor = vim "+HgCiDiff()"
It kind of works, but I would like that splited window would be in right side (now it opens up in left) and mercurial message would be focused window. Also :wq could be setted as temporary shortcut to :wq<CR>:q! (having an assumption that mercurial message is is focused).
Any suggestions to make this a bit more useful and less chunky?
UPDATE: I found vim split guide so changing vnew with rightbelow vnew opens up diff on the right side.
So I expanded my own code:
function! HgCiDiff()
"In .hgrc editor option I call vim "+HgCiDiff()"
"It opens new split with diff inside
rightbelow vnew
:.!hg diff
set ft=diff
saveas! /tmp/hgdiff.txt
execute "normal \<c-w>w"
endfunction
Yet It missed :wq mapping as :wqa, yet using :wqa is not that hard.
Sources of my vimrc is located here: http://hg.jackleo.info/vim-configs/src/08df5cb9d143/vimrc
Sources of my hgrc is located here: http://hg.jackleo.info/home-configs/src/22f5fb47a7d2/.hgrc
Update: as suggested by Randy Morris I updated my code and now it works just as I wanted. Thanks! Also added few extra features as the time went by.
function! HgCiDiff()
"In .hgrc editor option I call vim "+HgCiDiff()"
"It opens new split with diff inside
rightbelow vnew
setlocal buftype=nofile
:.!hg diff
setlocal ft=diff
wincmd p
setlocal spell spelllang=en_us
cnoremap wq wqa
cnoremap q qa
start
endfunction
Edit
Hmm I think this might not be what you are after on second reading. I understand you want a multi-file (unified) diff. I'd really use a hg-aware UI tool and a separate vim editor for the commit message. Sorry about that.
I'll leave the 'original' response stand in case you didn't know VCSCommand + Hg + Vim yet:
My weapon of choice is to abstract it all away with
vcscommand.vim : CVS/SVN/SVK/git/hg/bzr integration plugin
You would
:VCSVimDiff
to diffsplit against the repo version (also with Leadercv)
:VCSVimDiff <revid>
to compare against a specific revision.
My solution consists of three vim files. It doesn't require hg configuration changes, and only shows the diff for the files you're committing, if you've used hg commit file1 file2:
~/.vim/ftdetect/hg.vim
au BufRead,BufNewFile /tmp/hg-editor-*.txt set filetype=hg
~/.vim/syntax/hg.vim
" Vim syntax file
" Language: hg commit file
" Maintainer: Marius Gedminas <marius#gedmin.as>
" Filenames: /tmp/hg-editor-*.txt
" Last Change: 2012 July 8
" Based on gitcommit.vim by Tim Pope
if exists("b:current_syntax")
finish
endif
syn case match
syn sync minlines=50
if has("spell")
syn spell toplevel
endif
syn match hgComment "^HG: .*"
hi def link hgComment Comment
let b:current_syntax = "hg"
~/.vim/ftplugin/hg.vim
" Show diff while editing a Mercurial commit message
" Inspired by http://stackoverflow.com/questions/8009333/vim-show-diff-on-commit-in-mercurial
" and Michael Scherer' svn.vim
function! HgCiDiff()
let i = 0
let list_of_files = ''
while i <= line('$') && getline(i) != 'HG: --'
let i = i + 1
endwhile
while i <= line('$')
let line = getline(i)
if line =~ '^HG: \(added\|changed\)'
let file = substitute(line, '^HG: \(added\|changed\) ', '', '')
let file = "'".substitute(file, "'", "'\''", '')."'"
let list_of_files = list_of_files . ' '.file
endif
let i = i + 1
endwhile
if list_of_files == ""
return
endif
pclose
new
setlocal ft=diff previewwindow bufhidden=delete nobackup noswf nobuflisted nowrap buftype=nofile
silent exec ':0r!hg diff ' . list_of_files
setlocal nomodifiable
goto 1
redraw!
" nooo idea why I have to do this
syn enable
endfunction
call HgCiDiff()
Here's my variation based on Marius Gedminas and JackLeo's versions:
function! HgCiDiff()
" find files that were changed (not interested in added or deleted)
let changed_files = []
let pattern = '\vHG: changed \zs(.+)\ze'
while search("HG: changed", "W") > 0
let line_text = getline(line("."))
call add(changed_files, matchstr(line_text, pattern))
endwhile
let diff_cmd = "hg diff " . join(changed_files, " ")
" Reset cursor to beginning of the buffer
call cursor(1, 1)
rightbelow vnew
setlocal buftype=nofile
let diff_output = system(diff_cmd)
call append(0, split(diff_output, "\n"))
" Reset cursor to beginning of the buffer
call cursor(1, 1)
setlocal ft=diff
wincmd p
setlocal spell spelllang=en_us
cnoremap wq wqa
cnoremap q qa!
startinsert
endfunction

Can I use cppcheck when I execute :wq in Vim editor for c/c++ in a interactive way

Can anybody help me to get solution for my requirement?
Requirement is when a user exits from vim, cppcheck should happen and if any warning or error occurs then it should be prompted to a user.
Thanks in advance.
I assume you don't care if the command is executed asynchronously, since you're quitting the buffer anyway. You can use the :! command to run shell commands and :read to capture the output to a new window:
function! s:RunShellCommand(cmdline)
let first = 1
let words = []
" Expand and escape cmd arguments.
" shellescape() should work with '\'
for part in split(a:cmdline)
if first
" skip the cmd. ugly, i know.
let first = 0
else
if part[0] =~ '\v[%#<]'
let part = expand(part)
endif
let part = shellescape(part, 1)
endif
call add(words, part)
endfor
let expanded_cmdline = join(words)
" Create the new window
botright new
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
call setline(1, 'Showing output from cmd: ' . expanded_cmdline)
call append(line('$'), substitute(getline(2), '.', '=', 'g'))
" This is where actual work is getting done :-)
silent execute '$read !'. expanded_cmdline
" Uncomment the line below if you want the buffer to be
" non-modifiable
" setlocal nomodifiable
1
endfunction
Then you can define an autocommand for when a buffer is unloading:
au BufUnload *.cpp s:RunShellCommand('cppcheck %')
or a somewhat more generic command which you can call at any time:
command! -complete=shellcmd -nargs=+ Shell call s:RunShellCommand(<q-args>)
Now, to prevent closing your buffer, you have to remap :wq or :q to a function that will perform the aforementioned (plus perhaps some confirmation?), since once :quit is invoked, it cannot be aborted.

Resources