0

Let's say I have text like this,

SPAC     SPAC - Specific-Purpose Committee Campaign Finance Report 
SPAC-SS  SPAC-SS - Specific-Purpose Committee Special Session Report          
SPAC-T   SPAC-T -  PAC Special Pre-election (Telegram) Report of Contributions

Now how would I use vim-surround to surround to get,

'SPAC'     SPAC - Specific-Purpose Committee Campaign Finance Report 
'SPAC-SS'  SPAC-SS - Specific-Purpose Committee Special Session Report          
'SPAC-T'   SPAC-T -  PAC Special Pre-election (Telegram) Report of Contributions

I can use block surround entering visual-block mode with CONTROL + v, making the selection and using S', but I get

'SPAC    ' SPAC - Specific-Purpose Committee Campaign Finance Report 
'SPAC-SS ' SPAC-SS - Specific-Purpose Committee Special Session Report          
'SPAC-T  ' SPAC-T -  PAC Special Pre-election (Telegram) Report of Contributions

Ideally, I would have a better method that would do inner word. What would work in this situation, trimming the whitespace from both sides of the collection?

1

In my opinion the best way to do what you want is to use a substitution command:

:'<,'>s/[^ ]\+/'\0'

Which is decomposed like this:

'<,'>                  the range of lines you want to treat (you could use % is you want to change all the lines of the buffer, or use line numbers e.g. 1,10)
     s/                the substitution command
       [^ ]\+          all the characters until the first white space
             /
              '\0'     \0 is what you matched before and it is surrounded by quotes.

If you really want to use vim-surround you could use a macro. First empty your register with qaq, then on the first line use:

qa0ysW'jq

to do the following:

qa           record a macro in the register a
  0          move to the beginning of the line
   ysW'      surround the word with simple quotes
       j     move one line down
        q    stop recording

You can then use 10@a to execute the macro 10 ten times (so on the ten next lines)


Note that even with a macro you don't need the surround plugin:

qaI'<Esc>Ea'jq

Which means:

qa               record the macro
  I'             insert a quote at the beginning of the line
    <Esc>        exist insert mode
         E       go to the end of the first word
          a'     insert a quote after the word
            j    go down one line
             q   stop recording
1

Ideally, I would have a better method that would do inner word.

You can do that with :normal.

:%norm ysiW'

I assume you want an inner WORD not word.

You can also visually select the lines and then do:

:norm ysiW'

For more help see:

:h :norm
:h :range
  • This doesn't seem to care what I select it only ever quotes the first WORD. – Evan Carroll Oct 8 '18 at 22:35
  • @EvanCarroll, This is using :normal with a visual range, i.e. :'<,'>norm. This means that it is going to run the normal commands ysiW' on each line in that range. So it will surround the first word in each line in the visual selection with single quotes. See :h :norm, :h '<, and :h v_: for more information – Peter Rincker Oct 9 '18 at 17:39
  • I understand, but the example only used the first column because I wasn't aware that answers would presume I wanted just the first column. See this as a follow up. vi.stackexchange.com/q/17593/5078 – Evan Carroll Oct 9 '18 at 17:45
  • Sadly there is no native method to "run command on a visual block". Your best bet would be to do a substitution, a macro, or maybe using :! & awk. Surround does try to do different things based on the visual mode, but as you stated it does not help. You could also adjust your :normal like so `:execute "normal ".vertcol("'<")."\<bar>ysiW'" to take account for the column position of your visual block. – Peter Rincker Oct 9 '18 at 18:06

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.