Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visual mode snippet expansion #49

Closed
jandamm opened this issue Jul 6, 2020 · 23 comments · Fixed by #51 or #50
Closed

Visual mode snippet expansion #49

jandamm opened this issue Jul 6, 2020 · 23 comments · Fixed by #51 or #50

Comments

@jandamm
Copy link
Contributor

jandamm commented Jul 6, 2020

I'm currently migrating from UltiSnips.
It is possible to use $VISUAL there which is the text which was selected when triggering the snippet:
You select text, type an expansion keystroke, type the snippet and then again the keystroke (in insert)
Then the snippet is expanded and every appearance of $VISUAL is replaced. Not literally - using VISUAL as a placeholder was supported as well.

Reading the docs from Microsoft $TM_SELECTED_TEXT should be the equivalent. But I haven't got it to work yet.
Is this supported yet?

@hrsh7th
Copy link
Owner

hrsh7th commented Jul 7, 2020

You can use this solution.

TM_SELECTED_TEXT;log|<Plug>(vsnip-expand)

In this case, TM_SELECTED_TEXT behaves like $VISUAL or $TM_SELECTED_TEXT.

When you want to behave like ultisnips, please heads up ultisnips solution (I don't know ultisnips's $VISUAL workflow.)

Thanks.

@jandamm
Copy link
Contributor Author

jandamm commented Jul 7, 2020

Assuming these mapping

imap <expr> <C-l>   vsnip#available(1)  ? '<Plug>(vsnip-expand-or-jump)' : '<C-l>'
smap <expr> <C-l>   vsnip#available(1)  ? '<Plug>(vsnip-expand-or-jump)' : '<C-l>'

I would expect the following:

ihello<ESC>vb<C-l>
I entered stored 'hello' as $TM_SELECTED_TEXT and I'm still in insert.

abc<C-l>
I expand the snippet 'abc' where $TM_SELECTED_TEXT is 'hello'.

My use case is selecting text visually, and wrap it in a snippet.
Mostly selecting autocmd ... and quickly wrap it in an augroup with a snippet.

@jandamm
Copy link
Contributor Author

jandamm commented Jul 7, 2020

Actually the UltiSnips smap ... expand_or_jump is more complicated.

From what I've gathered this is the logic:

Is the selected text a snippet -> expand
Is cursor in an expanded snippet -> jump
else -> set selected text to $VISUAL

@hrsh7th
Copy link
Owner

hrsh7th commented Jul 7, 2020

Hm... Indeed, My provided solution does not support the your case (e.g. wrap by augroup etc).

OK, I will consider it.

Now, I have a question.
When expanding snippet on visual mode by ultisnips, how choose snippet from many candidates?
My understanding is that has no timing to choose snippet in this case.

@jandamm
Copy link
Contributor Author

jandamm commented Jul 7, 2020

An example would be:

aug -> augroup ${1:auc} ${2:test} $0
auc -> hello

It then would work like this

aug<C-l> the snippet expands and auc is selected in select mode.
Pressing <C-l> again would then insert the snippet ('hello').

With your plugin: aug<C-l>auc<C-l> would be the same.

I do this because I only have to change auc to change the snippet and it is just referenced inside of aug instead of changing every snippet where I want to use it.

@jandamm
Copy link
Contributor Author

jandamm commented Jul 7, 2020

I think a good addition would be <plug>(vsnip-visual-expand) where the visual selection is checked instead of the chars left to the cursor. Also the availability check would need to be updated/added for visual.

@hrsh7th
Copy link
Owner

hrsh7th commented Jul 7, 2020

I might misunderstand what you said.

Currently, IMO, I can't think your suggestion is useful...

For example, the above case should be enough aug -> augroup hello ${2:test} $0.


But I think we should implement visual snippet expansion as below behavior.

{
  "prefix": "wrap-tag",
  "body": [
    "<${1:tag}>",
    "\t$TM_SELECTED_TEXT",
    "</${1}>"
  ]
}

If it implemented, we can wrap HTML element by select&expand wrap-tag snippet in visual-mode.

@jandamm
Copy link
Contributor Author

jandamm commented Jul 7, 2020

The idea why I used ${1:auc} instead of hello was that when I change hello to hi i would have to change both aug and auc. Of course auc isn't just hello and has many tabstops of its own.
autocmd ${1:${2:VimEnter} ${3:*}} $0

It is a way to include another snippet. It isn't something that cannot be achieved otherwise but reduces copy&paste.

@hrsh7th
Copy link
Owner

hrsh7th commented Jul 7, 2020

vsnip has nested placeholder feature so your recent example already supported now, I think.

{
  "aug": {
    "prefix": ["aug"],
    "body": ["autocmd ${1:${2:VimEnter} ${3:*}} $0"]
  }
}

This snippet works fine as you expected.

Kapture 2020-07-07 at 20 20 57

@jandamm
Copy link
Contributor Author

jandamm commented Jul 7, 2020

How would I use wrap-tag?
Select it, press expand, type wrap-tag and press expand again?

@hrsh7th
Copy link
Owner

hrsh7th commented Jul 7, 2020

Currently, vsnip can't expand wrap-tag on visual-mode.

So we should implement mapping that add the ability to choose snippet on visual-mode.

@jandamm
Copy link
Contributor Author

jandamm commented Jul 7, 2020

Yes the nested placeholders work fine.

I would want to use nested snippets,` like this:

{
  "aug": {
    "prefix": ["aug"],
    "body": ["something", "autocmd ${1:${2:VimEnter} ${3:*}} $0", "Else"]
  },
  "auc": {
    "prefix": ["auc"],
    "body": ["autocmd ${1:${2:VimEnter} ${3:*}} $0"]
  }
}

Now I have "autocmd ${1:${2:VimEnter} ${3:*}} $0" twice and changing it would require changing aug and auc.

Ideally aug would have this body:
"body": ["something", "$auc", "Else"]
Where $auc is replaced with the auc snippet.

@hrsh7th
Copy link
Owner

hrsh7th commented Jul 7, 2020

Probably I understood what you want.

Hm... I think it should not support vsnip itself.
But vsnip has vsnip#anonymous API so I provide the way to enable it for you, please wait.

@jandamm
Copy link
Contributor Author

jandamm commented Jul 7, 2020

My idea was to use the visual selection as l:before_text in vsnip#get_context().

@jandamm
Copy link
Contributor Author

jandamm commented Jul 7, 2020

The select mode mapping I was looking for is this:

func Reselect()
        return "\<ESC>gv\<C-g>\<C-l>"
endfunc

smap  <C-l>   <C-g>o<ESC>a<C-r>=(vsnip#available(1) && !vsnip#expand())  ? '' : Reselect() <CR>

@jandamm
Copy link
Contributor Author

jandamm commented Jul 7, 2020

I checked what UltiSnips does in the visual mode mapping:

:call UltiSnips#SaveLastVisualSelection()<cr>gvs

In vsnips this would mean that this saves the currently selected text in the current context and provides this along with the next expanded snippet as $TM_SELECTED_TEXT.

@hrsh7th
Copy link
Owner

hrsh7th commented Jul 8, 2020

Which do you hope the <Plug>(vsnip-select-on-visual) or <Plug>(vsnip-expand-on-visual)?

I feel we talking about the two different feature.

Or, we talking about just the one feature if so, I want to understand it.

@jandamm
Copy link
Contributor Author

jandamm commented Jul 8, 2020

I think it's two features:

a) use visual selection in snippets as $TM_SELECTED_TEXT
b) expand snippets from select mode

a) this is how UltiSnips does it: #49 (comment)
There is a mapping to store the text from visual mode and then use it for the next snippet.

b) I figured out how to do this without any change of your plugin:
#49 (comment)

@jandamm
Copy link
Contributor Author

jandamm commented Jul 8, 2020

I believe vsnip#selected_text('Text') does what I'm looking for.

I'll test a bit and then report back.

@jandamm
Copy link
Contributor Author

jandamm commented Jul 8, 2020

I got it working.
I'm busy right now but I'll do a write up soon.

Would you accept a PR which makes this feature discoverable and makes it easier to use it? Wouldn't change the API only add better support for the mappings.

@hrsh7th
Copy link
Owner

hrsh7th commented Jul 8, 2020

My random thought are

  • It will be good to implement the 'b' feature in vsnip

    • I think that' better to add smap <Plug>(vsnip-expand) but <Plug>(vsnip-expand-or-jump) is not.
  • I think the 'a' feature is very useful

    • But I couldn't think good interface...

@jandamm
Copy link
Contributor Author

jandamm commented Jul 8, 2020

I have a somewhat working proof of concept. I'll create a PR when I've cleaned up.

@jandamm
Copy link
Contributor Author

jandamm commented Jul 8, 2020

I've created two PRs one for a) and one for b).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants