1

I'm trying to write a 2D matrix of characters. I can get a string of random characters with pwgen 4 1, for example. That gives me something like this.

ia6e

Is there a way to split this string up by characters in vanilla Vim? I need to quote each individual character and put some spaces in between. Eventually, I want to end up with something like this.

'i', 'a', '6', 'e'
1

Would the following substitutions help you?

:s/\(.\)/'\1', /g
:s/, $//

The first wraps all the characters with quotes and with comma and space afterwards (in the current line only). The second removes the last comma and space from the line (again, current line only).

  • Oooh, yeah. Capture each character, then put it in quotes and add a comma. Nice. That's easier than I thought! – 425nesp May 8 at 8:12
  • 2
    :s/./'&', /g is a bit shorter and (depending on the keyboard) might be easier to type. – Jürgen Krämer May 8 at 14:33
  • Neat. Can you explain what this is doing? – 425nesp May 11 at 5:41
  • In a Vim substitution, & represents the whole matched pattern. In this case, the pattern is any single character. So using & is the same as capturing the single character and using \1, in a cleaner way. – padawin May 12 at 9:05
0

You can use the :split function of vim to separate a given string to all its different character.

The basic split function that would do it for you would be something like:

split(current_word, '\zs')

A full command that would actually do the split is:

:execute "normal ciw" . string(split(expand("<cword>"), '\zs')) 

If you would like, you can create a function that would change the current word to its different characters. The function would be:

function! SplitCurrentWord()                                                                                                                                                                       
    let current_word = expand("<cword>")                                                                                                                                                       
    normal ciw                                                                                                                                                                                 
    for current_char in split(current_word, '\zs')                                                                                                                                             
        execute "normal a\'" . current_char . "\', "                                                                                                                                           
    endfor                                                                                                                                                                                     
    normal "xxx"                                                                                                                                                                               
endfunction

You can add it to your vimrc and load it when needed, or map it to a command or a set of keys. (with command! SplitWord call SplitCurrentWord)

  • Interesting... Doesn't split mean Split current window in two.? How does this work? – 425nesp May 11 at 5:44
  • You are talking about a different kind of split. The command split is indeed the command that would split a window in two. In here, I use the function split, which takes a string of characters and split them according to the given value. Reading again my answer, the first example is indeed a bit misleading about how to use the split, I edited the answer to make it easier to understand. – Omri Sarig May 11 at 14:58
0

I can never resist solving this sort of problem with a recursive macro.

First, the complete set of keystrokes required to record and playback the macro:

qqqqqs''EscPRightRighti,SpaceEscRight@qq@q

How it works

  1. qqqqq — Recursive macro boilerplate. This clears out the "q register and starts recording a new macro into it,
  2. s''EscP — Surround the character under the cursor with quotes*,
  3. RightRight — Move to the next character. If we're at the end of the line, this command will fail**, and the recursive macro will stop,
  4. i,SpaceEsc — Add the comma-space,
  5. Right — Move to the next character on the line,
  6. @qq@q — More boilerplate: when you are recording the macro, the first @q does nothing because we cleared out the "q register in Step 1. However, when playing back the macro, this will cause the macro to run again. The second q then stops and saves the recording, and the final @q plays back the macro.

* An alternative, here: s'Ctrl-R-' This variation is useful if you're ever trying to surround something with something longer than single characters, such as an HTML tag.
** If you've added > to your 'whichwrap' setting, then the second Right will instead move to the next line and your recursive macro will carry on splitting characters all the way to the end of the file! Replace Right with Space or l to fix, depending on which of these is missing from your 'whichwrap' setting. If you have all three keystrokes in your 'whichwrap', consider whether you really need all three "move right one character" commands to work in the same way at the end of a line.

Playing back on multiple lines

Once you've got the macro recorded, if you want to run it on multiple lines, you can use a command like the following, which will convert lines 5–10:

:5,10norm!@q

See :help :normal and :help ranges for more details.

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.