Suppose I have this string variable:

let foo = [
      \ 'no you are not foo',
      \ 'hi you must be foo?'

I want to enclose all the first 2 characters in foo with '< ' and ' >' resulting to this:

'< no > you are not foo'
'< hi > you must be foo?'

How can I do that?

  • And how do you do it now? I mean you obviously don't want us to answer with "goto no, insert < ..." do you? – Maxim Kim Nov 15 '18 at 6:17
  • 1
    Am I right that you want, for example, a function named Enclose that will transform all the string values of the list to have first 2 characters enclosed in < ... > ? – Maxim Kim Nov 15 '18 at 6:20
  • @MaximKim yes you're right, sorry I didn't clarrify my question, but yes tha'ts what I want. – John Fred Fadrigalan Nov 15 '18 at 11:49
  • Then either Christian Brabandt's answer or my will do the job – Maxim Kim Nov 15 '18 at 11:56

You can do it with this vimscript:

fun! EncloseString(str)
    return '< '.strcharpart(a:str, 0, 2).' >'.strcharpart(a:str, 2)

let foo = [ 'no you are not foo', 'hi you must be foo?']
call map(foo, {key, val -> EncloseString(val)})

EncloseString function is the helper one to use in a map function. map function updates foo list in-place using anonymous function aka lambda.

Without helper function you can use substitute (as in @Christian Brabandt answer):

call map(foo, {key, val -> substitute(val, '^..', '< & >', '')})

Instead of map you can traverse the list in imperative way with for:

let result = []
for str in foo
    call add(result, substitute(str, '^..', '< & >', ''))
| improve this answer | |
  • thanks for this! The one works for me is the first example, because it also wraps 2 characters wide even it it exists or not. +1 for the other examples – John Fred Fadrigalan Nov 15 '18 at 12:12

With a recent enough Vim you can use lambda (:help lambda) expressions in conjunction with the map() function.

So you could use:

call map(foo, { k,v -> substitute(v, '^\w\+', '<&>', '')})

which basically changes the list in place replacing the first word by <word>.

You can do it with older Vims using just plain map(), but than the quoting is usually nasty.

| improve this answer | |

For tasks like that many people use the surround plugin. To add brackets, you press ys, then the Vim motion (e), then the character (<). With the repeat.vim plugin, this can then be easily applied to other places via ..

Unfortunately, your particular use case (angle brackets with inner space) isn't handled by the plugin, because it has a special case for HTML tags on that. (But you could do it without the spaces, and then add spaces: yse>lyse<Space><Space>)

There's also vim-sandwich, a more configurable alternative.

| improve this answer | |

If this is for a one time use, you can also look for a simple solution without a plugin and without a complicated command to write.

At first in your particular use case I would go for a substitution command:

  • First visually select all the lines you want to modify. For example with your cursor on no you could use Vj
  • Then the substitution command:

    '<,'>s/\w\w/< & >
    '<,'>              the lines you want to act on, when you press : in visual mode it is directly inserted
         s/            start the substitution
           \w\w        match two alphanumerical characters (the first one on the line)
               /       second part of the substitution
                < & >  insert a literal "< " followed by what you matched followed by " >"

Still for this particular use case I would also use the visual block mode:

  • With your cursor on the n of no
  • Press Ctrl+v to start visual block
  • Go down one line with j, now you have n and h selected
  • Press I to start inserting in front of your selection
  • Insert <
  • Quit insert mode and go to the end of no (with e or fo
  • Press Ctrl+v to start visual block
  • Go down one line with j, now you have o and i selected
  • Press A to start inserting after your selection
  • Insert >

I think these solutions are interesting because they don't require you to think much before you can use them, they are really basic features. Of course the drawback is that if your input is more complex than what you gave as an example they might not scale well.

| improve this answer | |

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.