I would like to know how I could trigger a certain action when I'm within a certain environment when writing code/ latex using vim. For instance, suppose I'm writing tex and inside the align environment, then I'd like every equals sign I enter to be converted to &=.
What I'm thinking of now is rather cumbersome. This is pseudo code for what is in my vimrc. Here's what it looks like
Shortcut for environment opens start and end tag for align environment (Using imap)
The above action also initiates a counter variable, sets it to 1
If counter is 1, every equals sign I enter should be entered as an &=.
Shortcut to force counter to zero when I move out of the environment. (Using imap)
I would like to know if there is an easier way to get around this. This is just an example. The main idea here is for vim to have environment-awareness.
Looking forward to your suggestions.
I generally tackle this sort of problem after the fact. For instance, I write it with the normal =
signs and then visually select it the area and use :s/=/\&=/g
. If you want to do multiple things to the "environment" after the fact you can create a function and trigger a key to execute it. For example:
vnoremap <leader>la :call <SID>latexAlign()<cr>
function! s:latexAlign() range
exe ":'<,'>s/=/\&=/g"
" add more stuff here...
endfunction
However, I think your solution is better in case you go back and edit it later. The htmlcomplete file in vim handles this situation like this:
let stylestart = searchpair('<style\>', '', '<\/style\>', "bnW")
let styleend = searchpair('<style\>', '', '<\/style\>', "nW")
if stylestart != 0 && styleend != 0
if stylestart <= curline && styleend >= curline
let start = col('.') - 1
let b:csscompl = 1
while start >= 0 && line[start - 1] =~ '\(\k\|-\)'
let start -= 1
endwhile
endif
endif
You can see how it uses searchpair to determine if it is inside of the <style></style>
tags. See :help searchpair()
for more information.
This is a very interesting question, but I'm not sure that your suggested approach is the best way! I have attempted an answer, but this first iteration may not be perfect. I am assuming that a LaTeX environment is simply delimited by \begin
and \end
commands (my LaTeX is a bit rusty!).
Firstly you need a function to return the environment of the cursor position. My function below jumps to the previous \begin
command, then jumps forward to the matching \end
command, calculates whether the cursor is inside this region, and continues the process until a containing environment is found. It should handle nested environments. If not in a LaTeX environment, an empty string is returned.
function! GetTeXEnv()
let pos = getpos('.')
let win = winsaveview()
let env = ''
let carry_on = 1
let search_ops = 'bWc'
let b_start = line('.')
while carry_on
keepjumps let b_start = search('\\begin{',search_ops)
let search_ops = 'bW'
" Only accept a match at the cursor position on the
" first cycle, otherwise we wouldn't go anywhere!
let env = matchstr(getline('.'),'\\begin{\zs.\{-}\ze}')
let env_esc = escape(env,'*')
keepjumps let b_end = search('\\end{\s*' . env_esc . '\s*}','Wn')
if b_start == 0
" finished searching; stop
let carry_on = 0
elseif b_end > b_start && b_end < pos[1]
" not inside this env; carry on
let env = ''
elseif b_end > b_start && b_end >= pos[1] && b_start <= pos[1]
" found it; stop
let carry_on = 0
endif
endwhile
call setpos('.',pos)
call winrestview(win)
return env
endfunction
Now you can enquire the environment of the cursor using :echo GetTeXEnv()
.
To change the behaviour of the =
key, you need to create another function which returns &=
in the align environment, and =
otherwise:
function! TeXEquals()
return GetTeXEnv() =~ 'align\*\?' ? "&=" : "="
endfunction
Then you can remap =
in insert mode (for TeX files only)
autocmd FileType tex inoremap <silent> = <c-r>=TeXEquals()<CR>
This seems to work in my example LaTeX file. Let me know if you find any problems, or have any ideas for improvements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With