Search code examples
textvimpycharmnotepad++

Quickest way to add " at the end of a word in editors (vim, notepad++, etc.)


Let's assume we have a text file with the following format:

x,
xxx,
xx,
xxxxx,
xxx,
x,
xx,

and so on.

When importing data in python's panda, words need to be surrounded by " or '. Using either notead++ or Pycharm (vim interface) is there some kind of shortcut to add ' or " to all words in this file so that it would became:

'x',
'xxx',
'xx',
'xxxxx',
'xxx',
'x',
'xx'

I've been holding ALT key in notepad++ to add ' to the same column in the text file, but that only works when the words are aligned and have the same size. In the late nineties I remember a friend using a shortcut in VIM for doing that so I decided to ask what is the best way to do that since that's a very common operation. When the file is really huge, I use find and replace sometimes but it also only works when the file is well structured.

Any best practices in doing that?

Edit: Clarifying the question, I often get files in a "somewhat" CSV format. I say somewhat because it generally has problems. For now, let's just assume I can't use pandas.read_csv() and I have to copy paste the data into a python console for testing.

The file will have the format:

, col_name1, col_name2, col_name3, ... , col_namen ,
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
, col1, col2, col3, ..., coln ,
.
.
.
for n rows

I never know what col1 format will be before hand. It can be an int, a float, a date, a text or crap I need to discard.

The rows that are dates or strings need to be encompassed by quotes so that I can copy and paste them to a python terminal.

My memory may be failing since it has been more than 20 years but I remember a senior of mine from the university using vim positioning a cursor over colx, using a shortcut and then the words in all rows that were in colx position would be encompassed in quotes. I've looked around for that shortcut many times but I never found anything close to that shortcut. That's why I decided to ask it here.


Solution

  • There are many ways to do it in Vim, but nothing dedicated to that task out-of-the-box. Here are a few.

    Using a substitution:

    :%s/^[^,]*/'&'
    

    where:

    • ^ anchors the pattern at the beginning of the line,
    • [^,]* matches any character that is not a comma, zero or more times, as many as possible,
    • '&' replaces the matched text with itself, between single quotes.

    This has the effect of quoting whatever comes before the first ,. Of course, the pattern will need to be adjusted to deal leading whitespace or other peculiarities.

    Using a one-off macro:

    :%normal ^ct,'<C-v><C-r>"'
    

    where:

    • :[range]normal <cmd> executes normal mode <cmd> on every line in [range], here on every line in the buffer,
    • ^ moves the cursor to the first non-blank character of the line,
    • ct, cuts the text from the cursor to the first comma, exclusive, and enters insert mode,
    • ' inserts a single quote,
    • <C-v><C-r> is how you insert a literal <C-r> (^R) in this context,
    • ^R" inserts the text that was last cut,
    • ' inserts another single quote.

    In practice, everyone has the Surround plugin, which admittedly makes this a lot more intuitive:

    :%normal ^yst,'
    

    Both approaches work as-is with your first sample text and can be mapped if you have to that very often:

    xnoremap <F5> :normal ^ct,'<C-r>"'<CR>
    

    You could probably even use AWK, here.

    This is all very basic, though, and both your description of what that coworker did and your more realistic sample make me think that they either:

    • used a bunch of highly specific custom mappings/commands,
    • used mappings/commands provided by one or more third-party plugins.

    Vim users tend to create the first kind a lot, as their needs evolve. They tend to be very context-dependent and will be difficult to replicate with so little info. Moreover, Vim emulators such as IdeaVim may not have all the features needed. If you want to take that road, then the couple of examples above are as good a foundation as any but you will have to do all of the legwork.

    Since Vim emulators are not Vim, third-party Vim plugins can't be used and whatever plugin your coworker used can't be used in your context. If you can use actual Vim, look for a dedicated CSV-oriented plugin or maybe more low-level ones like one that would provide a "column" text object compatible with your notion of "column". Assuming…

    • such a plugin exist and exposes a ic text object,
    • you have the Surround plugin,

    then you would only need to position the cursor in the column and do:

    ysic'
    

    But that's a lot of assumption.