8

I am writing a VimL function that, in insert mode, allows a <BS> through the opening part of a pair ([, {, etc.) to delete the closing part of the pair if it is the next character after the cursor (much like auto-pairs and vim-autoclose). This function will be different because the closing part of the pair will not be deleted if there are unbalanced pairs.

Examples:

The format is <initial> => <result-after-backspace> where my cursor is in front of the |.

((|)    =>   (|)

((|))   =>   (|)

(|)     =>   |

(defn   =>   (defn
  (|)          |)

How can I determine whether or not the pairs are unbalanced before I go ahead and delete the closing pair?

I have tested both auto-pairs and vim-autoclose. With both plugins the closing part of the pair is always deleted.

12
  • Could you clarify your preface? Do you wish to avoid all plugins, or just ones similar to the two you mention? If the latter, what about those two do you not like?
    – Tom
    Feb 13 '15 at 19:11
  • I do not want to use any plugins for this. I've updated the preface.
    – user489
    Feb 13 '15 at 19:14
  • 1
    I've voted to close this question. I think the basic topic as such is fine, but your restrictions make it a "please write some code for me plz kthxbye"-question right now. I don't think we want to allow these sort of questions here... Feb 13 '15 at 23:07
  • 1
    @Carpetsmoker Beyond the wording of this question is a problem that has yet to be solved in any plugin that I have seen. It seems clear to me that once this question is answered successfully, every auto-closing or auto-pair type plugin will be able to benefit from its solution. How would you suggest I change the wording to make it acceptable?
    – user489
    Feb 13 '15 at 23:13
  • 2
    @merb, the paredit plugin does exactly what you want. If you want that functionality without actually using the plugin then I suggest you examine the source on github. I think that would be more instructive than me trying to reproduce a version of it here. github.com/kovisoft/paredit Feb 14 '15 at 16:56
1

If I understand your question correctly, the key is to determine whether the character on the cursor is a matched delimiter.

Consider the normal mode commands v%"zy and v%%"zy.

  • If the cursor is on a matched delimiter, then the first command will yank a string of length at least 2—the delimiter, its pair, and any text in the middle—into @z. The second will yank a string of length exactly 1—again, the delimiter itself—into @z.
  • If the cursor is on an unmatched delimiter, then the first command will yank a string of length 1—the delimiter itself—into @z. Abort.
  • If the cursor is not on a delimiter and there is a delimiter in the line, then the second command will yank a string of length greater than 1 into @z. Abort.
  • If the cursor is not on a delimiter and there is no other delimiter in the line, then the first command will yank a string of length exactly 1—the character itself—into @z. Abort.

Thus, we have the following result:

The cursor is on a matched delimiter if and only if the normal mode command v%"zy yanks a string of length at least 2 into @z and the normal mode command v%%"zy yanks a string of length exactly 1 into @z.

Hints for VimL: :norm ... and strlen(@z) will help here.

2
  • Does this answer your question, or am I missing something?
    – wchargin
    Feb 21 '15 at 3:42
  • Determining whether or not the character on the cursor is matched isn't exactly the key. The key is to determine whether or not a given form is balanced. If the form is balanced and we find ourselves in this position: (|), pressing <BS> should delete both. However, if the top level form is unbalanced, like this: (defn (|), pressing <BS> should only delete what would normally be deleted - in this case leaving us with (defn |).
    – user489
    Feb 21 '15 at 19:26
1

Ok so I ended up going through paredit.vim and pulling out some functions to create this: vim-pear. It inserts and deletes delimiters in pairs while maintaining a balanced state.

3
  • Cool :-) How do I use it? Can I just install it and it will be enabled by default? Is it also possible to enable/disable this only for specific filetypes? Feb 23 '15 at 16:36
  • Enabled for everything by default. Submit a PR if you want anything like that. I may do it myself at some point.
    – user489
    Feb 23 '15 at 16:52
  • The link is (currently) broken.
    – Rich
    Jan 13 '16 at 15:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy