A vim plugin that emulates all of the powerful IDE features of MATLAB in vim so you don't need to run the full GUI.
git clone https://mcol.xyz/code/vimlab
Log | Files | Refs | README | LICENSE

commit cf297918882073c40426220482933c888dda9279
parent 146ad84226797cdd5a2f57d9bdf2240106f8603d
Author: mcol <mcol@posteo.net>
Date:   Sun, 28 Oct 2018 00:45:24 +0100

big organisation

Diffstat:
A.gitignore | 17+++++++++++++++++
Mftplugin/matlab.vim | 102++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Aop.m | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asyntax/add-syntax-functions.sh | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msyntax/matlab.vim | 2++
5 files changed, 252 insertions(+), 32 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,17 @@ +doc/tags +syntax/custom-syntax +syntax/custom-function-directories + +*.s[a-w][a-z] +*.un~ +Session.vim +.netrwhist +*~ + +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db diff --git a/ftplugin/matlab.vim b/ftplugin/matlab.vim @@ -35,14 +35,16 @@ let &cpo = s:save_cpo + " Everything below here is my own configuration of found pieces. + "------------------------------------------------------------------ " mlint code checking "------------------------------------------------------------------ " mlint is symlinked into $PATH from <MATLABROOT>/bin/<ARCH> " mlint.vim from vim-matlab appears to not get sourced automatically -source ~/.vim/bundle/vim-matlab/compiler/mlint.vim +source ~/.vim/bundle/vimlab/compiler/mlint.vim " check code by running mlin nnoremap <Leader>cc :make<CR> @@ -56,8 +58,9 @@ nnoremap <Leader>cp :cp<CR> "------------------------------------------------------------------ -" This section from http://github.com/elmanuelito/vim-matlab-behave +" Folding "------------------------------------------------------------------ + " make section title bold highlight MATCELL cterm=bold term=bold gui=bold match MATCELL /^%%[^%]*$/ @@ -74,15 +77,11 @@ endfunction setlocal foldmethod=expr setlocal foldexpr=MatlabFolds() -" Save matlab session manually -map <Leader>ss :w<CR>:mksession! ~/.cache/vim/sessions/matlab-session.vim<Cr> -" and automatically on exit -nnoremap XA :mksession! ~/.cache/vim/sessions/matlab-session.vim<CR>:wqa<CR> + +autocmd BufWinLeave *.m mkview " remember folding layout +autocmd BufWinEnter *.m silent loadview -"--------------------------------------------------------------------- -" Format title line of folded sections to just show text and no. lines -"--------------------------------------------------------------------- function! MyFoldText() " {{{ let line = getline(v:foldstart) @@ -109,44 +108,83 @@ let g:slime_dont_ask_default = 1 let g:slime_default_config = {"socket_name": "default", "target_pane": "1"} let g:slime_paste_file = "/tmp/slime_paste" +" open word under cursor using op.m function +" this opens variables in the variable editor, or text files in vim. The second argument +" (i.e. 'vimlab') makes the file open in the vim server with that name +nnoremap <silent> <CR> yiw:SlimeSend1 op <C-r>" 'vimlab'<CR> +nnoremap <silent> <Leader><CR> yiw:SlimeSend1 op <C-r>"<CR> + + +""" Running code + " F9 will send paragraph or visual selection map <F9> <C-c><C-c> + " F8 will run current line map <F8> <Esc>ms0v$<F9>`s -" F7 will run the current small word + +" F7 will run the current small word map <F7> <Esc>msviw<C-c><C-c>`s + " F4 will run the current section -map <F4> ms:execute 'try \| foldopen! \| catch \| \| endtry'<CR>$?%%\\|\%^?<CR>v$/%%\\|\%$<CR>?^\h<CR>$<F9>`s:let @/=""<CR> -" F2 will run entire file -"map <F2> <Esc>msggvG<F9>`s -map <F2> <Esc>:let @" = expand("%")<CR>:SlimeSend1 <C-r>"<CR> +map <silent> <F4> ms:mkview<CR>:execute 'try \| foldopen! \| catch \| \| endtry'<CR>$?%%\\|\%^?<CR>v$/%%\\|\%$<CR>?^.*\S<CR>$<F9>`s:let @/=""<CR>:loadview<CR> + +" F2 will call script by title, so must be on path +map <silent> <F2> <Esc>:let @" = expand("%")<CR>:SlimeSend1 <C-r>"<CR> -" open word under cursor -map <CR> yiw:SlimeSend1 op <C-r>"<CR> +" list variables +nnoremap <silent> <C-w> :SlimeSend1 who<CR> -" debugging -nnoremap <silent> <Leader>dq :SlimeSend1 dbquit all<CR> -" set/clear is <F12> normally. quit is <S-<F5>> -nnoremap <silent> <Leader>ds ms:let @" = "dbstop in " . expand("%") . " at " . line(".")<CR>:SlimeSend1 <C-r>"<CR>A %%% STOP %%%<Esc>`s -nnoremap <silent> <Leader>dc :let @" = "dbclear in " . expand("%") . " at " . line(".")<CR>:SlimeSend1 <C-r>"<CR>:.s/ %%% STOP %%%//<CR> -nnoremap <silent> <F10> :SlimeSend1 dbstep<CR> -nnoremap <silent> <F5> :SlimeSend1 dbcont<CR> -nnoremap <silent> <Leader>de :SlimeSend1 dbstop if error<CR> + +""" Debugging todo: make set and clear a toggle (and add F12 to this for normal matlab behaviour) + +" (a)dd +nnoremap <silent> <Leader>a :let @" = "dbstop in " . expand("%") . " at " . line(".")<CR>:SlimeSend1 <C-r>"<CR>:call matchaddpos('WildMenu', [line('.')], 10, line('.'))<CR> + +" (c)lear +nnoremap <silent> <Leader>c :let @" = "dbclear in " . expand("%") . " at " . line(".")<CR>:SlimeSend1 <C-r>"<CR>:call matchdelete(line('.'))<CR> + +" (s)tep +nnoremap <silent> <Leader>s :SlimeSend1 dbstep<CR> +nnoremap <silent> <F10> :SlimeSend1 dbstep<CR> + +" continue (g for go) +nnoremap <silent> <Leader>g :SlimeSend1 dbcont<CR> +nnoremap <silent> <F5> :SlimeSend1 dbcont<CR> + +" stop on (e)rror +nnoremap <silent> <Leader>e :SlimeSend1 dbstop if error<CR> + +" e(x)it debugging +nnoremap <silent> <Leader>x :SlimeSend1 dbquit all<CR> + +" (f)lush markers +nnoremap <silent> <Leader>f :call clearmatches()<CR>:SlimeSend1 dbclear all<CR> + +" dbstack, dbup and dbdown +nnoremap <silent> <Leader>ds :SlimeSend1 dbstack<CR> +nnoremap <silent> <Leader>du :SlimeSend1 dbup<CR> +nnoremap <silent> <Leader>dd :SlimeSend1 dbdown<CR> "------------------------------------------------------------------ -" Misc settings +" Writing "------------------------------------------------------------------ " map hash sign to percentage sign for commenting inoremap # % " add shortcuts to write chunks of code -nnoremap <Leader>f ofor <CR>end<Esc>kA -nnoremap <Leader>i oif <CR>end<Esc>kA -nnoremap <Leader>e oend<Esc> +inoremap for<space> for<space><Esc>ms/^$<CR>iend<Esc>`s<CR>=ipA +inoremap if<space> if<space><CR>end<Esc>kA +inoremap switch<space> switch<space><CR>case<CR>end<Esc>kkA +" echo synIDattr(synIDtrans(synID(line("."), col("."), 0)), "name") +" the line above will tell you if the cursor is in a comment -" list variables -nnoremap <silent> <C-w> :SlimeSend1 who<CR> +" Save matlab session manually +map <Leader>ss :w<CR>:mksession! ~/.cache/vim/sessions/matlab-session.vim<Cr> +" and automatically on exit +nnoremap XA :mksession! ~/.cache/vim/sessions/matlab-session.vim<CR>:wqa<CR> + +" ctrl-i to indent the whole file +nnoremap <C-i> msgg=G`szz -" open file under cursor -"nnoremap <CR> yiw:e **/<C-r>"*<CR> diff --git a/op.m b/op.m @@ -0,0 +1,98 @@ +function exitcode = op(name, server, term) +% +% This function will open what is passed to it based on what it is: +% +% If name is a variable, it will open it in the variable editor. +% +% If name is an m file, it will open it in vim via the system command. +% +% If you have a function and variable with the same name, WHICH YOU SHOULDNT, +% this will open the file, not the variable. +% +% The purpose of this is to bind the enter key in vim to send a command to +% matlab to execute this function with the word under the cursor. i.e. +% op('aWordInVim', 'vimlab'), which will either open aWordInVim in the variable +% editor, or send it to the vimlab vim server instance. +% +% There is a limitation, and that is that this can only open variables from the +% base workspace. +% +% INPUTS: +% +% name : a string referring to the name of a variable or file on the +% path. +% +% server : (optional) the name of a running vim server instance. If this +% is not given, or is given empty, then a new terminal window is created +% and the file is opened in vim. If it is given, the file will open in +% that vim server. +% +% term : (optional) a string referring to the terminal program used to +% open a new terminal window running vim. If this is empty or not given, +% it will default to 'urxvtc'. +% +% +% OUTPUTS: +% +% exitcode : the exit code returned from the executed system command. +% This might be useful for debugging. +% + + +% deal with inputs +if nargin < 3 + term = 'urxvtc'; +end + +if nargin < 2 + server = ''; +end + + +% Get returned value from exist(name) in base workspace +exp = strcat('exist("', name, '")'); +existence = evalin('base', exp); + + +% open the result +switch existence + + case 1 + % name is a variable + openvar(name); + return + + case 2 + % name is an m file on the path + file = which(name); + + case 5 + % name is a built in function + path = split(which(name), {'(', ')'}); + file = which(path{2}); + + case 6 + % name is a matlab p-code file + sprintf('%s is matlab p-code and cannot be opened.', name) + return + + otherwise + % name is something else + sprintf('%s was not found', name) + return +end + + +% open file in external editor +if isempty(server) + % a new terminal window will open + command = sprintf('%s -e bash -c "vim %s"', term, file); + +else + % a vim server is running + command = sprintf('vim --servername %s --remote %s', server, file); + +end + +exitcode = system(command); + diff --git a/syntax/add-syntax-functions.sh b/syntax/add-syntax-functions.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# +# This script will search the folders specified in the +# custom-function-directories file, find all the *.m files, and add their names +# to the custom-syntax file in a form that can be sourced for syntax +# highlighting. +# +# The file is overwritten each time this is run, so removing a directory from +# custom-function-directories will remove its m files from the syntax group. +# +# The custom-syntax file is then sourced by the syntax file to provide syntax +# highlighting to custom functions. +# +# This can be automated by adding something like this to your crontab (the path +# may need changing): +# 0 12 * * 1 $HOME/.vim/bundle/vimlab/syntax/add-syntax-functions.sh +# + + +# This file lists directories in which all m files will be added for syntax +# highlighting (the file may need creating as it is not tracked by git) +file=$(dirname "$0")/custom-function-directories + + +# This is the output file, generated fresh each time, which is sourced by the +# main syntax file +vimfile=$(dirname "$0")/custom-syntax + + +# check input file exist +if ! [ -f $file ] +then + printf "%s does not exist. You need to create it and add directories to it.\n" "$file" + exit +fi + + +# function to run +cmd() { + # find has trouble with expanding '$HOME' so this does that for it + dir=$(echo $1 | awk -v home=$HOME '{ gsub(/^~/,home,$0); print }') + + # this finds all .m files and outputs the name to a temp file + find $dir -type f -name "*.m" -printf "%f\n" >> $tmp +} + + +# this makes the temp file, and runs the above cmd function on every directoy +# listed in the custom-function-directories file +tmp=$(mktemp) +while read -r +do + cmd "$REPLY" +done < $file + + +# At this point, the temp file is a list of .m files. This section sorts them to +# remove any duplicates, removes the newline characters, removes the .m +# extensions, adds spaces between words, and prefixes it all with the vim +# command, allowing it to be sourced. + +sort -u $tmp -o $tmp +tr -d "\n" < $tmp > $vimfile +sed -i "s/\.m/ /g; s/^/syn keyword matlabFunc /1" $vimfile + diff --git a/syntax/matlab.vim b/syntax/matlab.vim @@ -306,6 +306,8 @@ syn keyword matlabFunc hdf hdf5 hdf5info hdf5read hdf5write hdfinfo hdfread hdft "Band-Interleaved Data syn keyword matlabFunc multibandread multibandwrite +"Custom m files +runtime syntax/custom-syntax " Define the default highlighting. " For version 5.7 and earlier: only when not done already