Placeholders interpolated from vim script

Asked by Marshall Eubanks

So, what would be the best way to do this?

I need to create a snippet which calls a vimscript function, the output of which must contain placeholders.

As far as I can figure, it has to be vimscript, as it calls the synIDattr() vim function to determine the current syntax, so that the return may depend on the current syntax.

Edit: To be clear, I want to write a vim function which does the following:

function! Foo()
return \sqrt[${1:n}]{${2:VISUAL:radicand}}$0
endfunction

And is called by a snippet:

snippet bar
`!v Foo()`
end snippet

Where the placeholders are interpreted as such. (It goes without saying that real function will have more than one possible return.)

Question information

Language:
English Edit question
Status:
Answered
For:
UltiSnips Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:

This question was reopened

Revision history for this message
Marshall Eubanks (marshaul) said :
#1

Well, I just realized that my idea won't even work in the first place, since the variable "t" doesn't do what I thought it did. (Doh!)

So.... how can I output working placeholders via a function (any kind of function, really)?

Revision history for this message
SirVer (sirver) said :
#2

So basically you have two problems to solve: 1. You want Ultisnips to fire on a trigger. 2. You want to have a function called which outputs a string to be parsed and expanded as a snippet.

2 is solved for you in Ultisnips. See :help UltiSnips_Anon. But this is thought to be called from some script or function that is already running, e.g. triggered from an imap.

1 is not currently implemented in UltiSnips.

I would suggest the following solution for your problem. For each "region type" define a new filetype, e.g. latexmathmode inside math mode. Therein define the snippets as usual, e.g, in ~/.vim/Ultisnips/latexmathmode.snippets.

Now either remap the tab key to a function that sets the filetype to eg. tex.latexmathmode (note the dot!) and then proxies to the Ultisnip function OR make a CursorMoved autocommand that keeps the ft updated. Everything should work then as expected.

I realize that triggering a simple function and inserting its output can be very useful. It would also be nice if one could add tabstobs programmatically from inside snippets. But alas, both is currently not supported.

Revision history for this message
Marshall Eubanks (marshaul) said :
#3

That solution actually does have at least one attractive side effect.

It leaves me with a couple of questions/concerns:

1. How many CursorMoved autocommands are already running? Do they have a potential to slow down the editor, executing as they do (I presume) just about anytime anything happens (i.e. each character that is typed in insert mode)?

2. Does changing the filetype in this fashion also mean that I'll need new (duplicate) maps and ftplugins for my new "filetype"? Or will changing it in this fashion only affect the choice of snippets available?

Revision history for this message
SirVer (sirver) said :
#4

1. At least one from UltiSnips. Likely more. Ultisnips does quite some work in this Autocommand and I doubt that you can feel the difference. You can get a list of the definded commands using :au CursorMoved and :au CursorMovedI. More info in the vim help on autocommands.

2. No, you will not need new mappings. But dotted filetypes affect the whole of vim. As the new filetype names are made up by you, they do not have any ftplugin or syntax defined, therefore you will likely only have the new snippets and no other behavior change. Read the section *UltiSnips-adding-snippets* in the help and :help 'ft'.

Revision history for this message
Marshall Eubanks (marshaul) said :
#5

Thanks, this seems like a workable – actually pretty good – solution to my problem.

Revision history for this message
Marshall Eubanks (marshaul) said :
#6

Thanks SirVer, that solved my question.

Revision history for this message
Marshall Eubanks (marshaul) said :
#7

I know this is no longer directly related to UltiSnips, but I just can't get it to work.

au CursorMoved * call Wtf()

 function! Wtf()
      call CurrentSyntax()
      if (IsMath())
          set filetype=tex.latexmathmode
      else
          set filetype=tex.latexnormal
      endif
  endfunction

Error detected while processing /Users/marshalleubanks/.vim/ftplugin/tex_functions.vim:
line 48:
E127: Cannot redefine function Wtf: It is in use

Eh? Any Idea what's going on here?

Revision history for this message
Marshall Eubanks (marshaul) said :
#8

It seems as though I'm doing the set filetype wrong, as it works if, say, I echo "it's math" or "it's not math" instead of setting the filetype.

Revision history for this message
Marshall Eubanks (marshaul) said :
#9

I figured it out. The problem is defining the function in the ftplugin area. Either it must be defined elsewhere, or it must check for its own existence.

Revision history for this message
Marshall Eubanks (marshaul) said :
#10

Thanks SirVer, that solved my question.

Revision history for this message
Marshall Eubanks (marshaul) said :
#11

Ok, I've definitely got some unintended recursion going on. I'm sure it has to do with setting the filetype repeatedly.

When I was just making echos in the function called by each CursorMoved event, things were fast.

However, as soon as I figured out how to change the filetype:

if !exists("*Wtf")
 function! Wtf()
  call CurrentSyntax()
  if IsMath()
   set ft=tex.latexmathmode
  else
   set ft=tex.latexnormal
  endif
 endfunction
endif

Things began to get real slow. Specifically, there is now a noticeable delay between when a cursor movement is keyed and when it finally occurs on the screen.

Interestingly, from the time vim is started, the delay between keystroke and cursor movement grows with each successive movement. So, the first time the cursor is moved, it's only a short delay. By about the 5th time, the delay has increased to about 4 seconds.

Revision history for this message
SirVer (sirver) said :
#12

This becomes harder to debug now as there are too many moving parts. My guess is that you reinstall the auto commands often, maybe every cursor moved. Check :au for that. Also switching filetype can be pretty expensive, so I would check if it really should change before setting ft.

If you cannot figure it out you have to provide your full .vim and vimrc for download, otherwise I cannot know what's going on.

Revision history for this message
Marshall Eubanks (marshaul) said :
#13

Ok, so I checked :au immediately upon running vim, and I see the following:

CursorMoved
    * call Wtf()
              call Wtf()
              call Wtf()
              call Wtf()
CursorMovedI
    * call UltiSnips_CursorMoved()
LatexBox_HighlightPairs CursorMovedI
    *.tex call s:FindMatchingPair('i')
CursorMovedI
    * call Insertmove()
              call Insertmove()
              call Insertmove()
              call Insertmove()

I can confirm that, after each cursor movement, the repetitions in this list grow by a factor of 2.

Revision history for this message
Marshall Eubanks (marshaul) said :
#14

I added some basic logic to prevent it from changing filetype unless the syntax actually changed since the last cursor move.

Now, the repeated function calls start at 2 repetitions, and only increase by 1 for each cursor movement, and only then when the syntax "zone" actually has changed!

Still, though, something is causing them to build up in the autocmd. Seems like something is executing the autocmd whenever the filetype is set.

Revision history for this message
SirVer (sirver) said :
#15

I will provide you with help on this once more, but then you are on your own because we are now no longer in the domain of Ultisnips.

The files you send me are not your full vim config, especially the part where you source tex_functions.vim is not included. However, the way you set your autocommands will lead them to be set whenever the file is sourced. You want to use augroups to prevent that and/or maybe even buffer local auto commands:

augroup SuperCleverLatex
   au!
   au CursorMovedI <buffer> call Insertmove()
   au CursorMoved <buffer> call Wtf()
augroup END

Revision history for this message
Marshall Eubanks (marshaul) said :
#16

Should have been clear; the tex_functions.vim is an ftplugin, so it's sourced in that fashion.

At any rate, that's moot now, because your suggestion fixed the issue. Even better, I actually get what was going on, now! =)

Things are nice and snappy, too. Looks like I'm in business.

Thanks again.

Revision history for this message
Marshall Eubanks (marshaul) said :
#17

Sorry to keep bugging you with this, but I now have a problem which, alas, seems to be back in the domain of UltiSnips.

So, I now have two filetypes, "tex.latexmathmode" and "tex.latexnormal".

Everything works exactly as expected in normal mode, but in math mode my snippets do not expand at all.

Best as I can tell, the filetype is correctly set. :set ft returns the expected result. Anyway, according to my logic, it should either be one type or the other, thus returning something (if the wrong something); yet the normal mode result isn't returned instead.

Also, I switched the set filetype statements, setting mathmode when it should be normal and vice-versa. I got the mathmode result in normal mode, but still no expansion whatsoever in math mode.

Furthermore, the regular latex snippets (from tex.snippets) don't expand in math mode either.

Somehow my logic is neglecting something, as I've successfully used syntax checking to disable expansion in math mode! Too bad this is not the intended result.

I've emailed you updated files.

Thanks again for your time and help. I really appreciate it.

Revision history for this message
SirVer (sirver) said :
#18

Works for me. I made two test snippets, both with the trigger test and the ioption and one expands to normal, the other to math. This is my input:

uuutestuuu
$$uuutestuuu$$

moving the cursor behind the first test gives uuunormaluuu and in the second line it gives uuumathuuu. I suspect two problems here:

1) you do not grok snippet options. your () snippet will not work correctly. Go read the f**** manual, please.
2) syntax elements seem to be undefined on whitespaces. For example
$$ uuu<-- ft here is sometimes still normal.
I cannot say it this is a bug in your code or intended behavior by the syntax highlighting.

This is no Ultisnips issue though. The next time you have to prove me first that your problem is related to Ultisnips, I cannot provide personal coding lessons for all Ultisnips users, sorry.

Revision history for this message
Marshall Eubanks (marshaul) said :
#19

1) Evidently not.

2) Yeah, the plan is to get the basic mechanics working right, then fine-tune things like the IsMath() function (that's why it's a function, after all).

I'm sorry to pester you with so many questions. BTW, I have had the manual in front of me the whole time. It is, however, rather dense at times.

Can you help with this problem?

Provide an answer of your own, or ask Marshall Eubanks for more information if necessary.

To post a message you must log in.