UltiSnips - The Ultimate Snippet Solution for Vim

How to indent multiple lines interpolated?

Asked by Alessio Bolognino on 2012-08-09

The idea is to write multiple lines, interpolate them in
some way and write them in two places, with different
indentation. I thought I could use vim.eval('col(".")') to
get the starting column number of the duplicated text
but it doesn't really work as I expected.
A simple snippet the show the problem is the following:

 snippet test
 original:
 ${1:txt}

 one indent: `!p
 ind = int(vim.eval('col(".")'))
 for x in t[1].splitlines():
  snip.rv += '\n' + (ind * " ") + x
 `
  two indents: `!p
 ind = int(vim.eval('col(".")'))
 for x in t[1].splitlines():
  snip.rv += '\n' + (ind * " ") + x
 `
 endsnippet

What I want to do is to have text like this:

original:
first_line
second_line
third_line

one_indent:
\t first_line
\t second_line
\t third_line

two indents:
\t \t first_line
\t \t second_line
\t \t third line

is there a way to achieve this?

Question information

Language:
English Edit question
Status:
Solved
For:
UltiSnips Edit question
Assignee:
No assignee Edit question
Solved by:
SirVer
Solved:
2012-08-10
Last query:
2012-08-10
Last reply:
2012-08-10
Alessio Bolognino (themolok) said : #1

launchpad messed with my code, so I paste the snippet on pastebin: http://pastebin.com/raw.php?i=hsTXqzxp
and this is the result I want to achieve: http://pastebin.com/raw.php?i=pSpLgHay

SirVer (sirver) said : #2

The snippet you need looks like this:

snippet test
original:
${1:txt}

one indent: `!p
snip >> 1
for x in t[1].splitlines():
   snip += x
`

two indents: `!p
snip >> 2
for x in t[1].splitlines():
   snip += x
`
endsnippet

You need to tell UltiSnips which indent you want, because there is plenty of trickiness with expandtab, shiftwidth, sts and ts. Look at the documentation and search for "mkline", ">>", "shift" and "snip +=" for explanations.

Alessio Bolognino (themolok) said : #3

That's not exactly what I was looking for: I wanted to pass to my python script the column number of "`!p", (in the first case it would be 13 and in the second case 18), anyway your solution is good enough for what I need it now.
My question is kind-of answered but I'd still like to know if there is a way to get the column number of the start of the "interpolation". If there is no way to do that, I'll close this question.
Thank you.

Best SirVer (sirver) said : #4

you can pass the indent to mkline directly. This here will ident 5 spaces, then 9 spaces:

snippet test "Description"
${1:text}

indent 1: `!p
for x in t[1].splitlines():
   snip.rv += "\n" + snip.mkline(x, " " * 5)`

indent 2: `!p
for x in t[1].splitlines():
   snip.rv += "\n" + snip.mkline(x, " " * 9)`

endsnippet

Note that UltiSnips will insert the indent you give to mkline verbatim, that is expandtabs (tabs->spaces conversion) will be ignored. Also, the indent is from the beginning of the line and does not take the starting column of the snippet into account (in this example, the python interpolation will always start in colum 6 and 10 respectivlely, even if you trigger the snippet in column 10, this can be solved by adding int(vim.eval("indent('.')")) to the indent numbers respectively. This has some trickyness of its own however :)

Alessio Bolognino (themolok) said : #5

Thanks SirVer, that solved my question.