1

I'm trying to make a search and replace to format the following type of strings.

INPUT

someName0 : in std_logic;
someName1 : in integer;
someName2 : out unsigned;
someName3 : out std_logic_vector(3 downto 0);

OUTPUT

someName0 : in    std_logic;
someName1 : in    integer;
someName2 :   out unsigned;
someName3 :   out std_logic_vector(3 downto 0);

So I'm going to have two search and replaces. First one works on the in signals. However "in" also matches "integer", so I need a way to specify to ignore those matches. I've tried using the following but it is saying the pattern wasn't found.

:%s/\<: in \>/: in    /g

The basic problem then seems to be how to do a search and replace on some specific string based on what the following character is. Or maybe I'm just taking a horrible approach.

Thanks.

2 Answers 2

1

It's actually simpler than doing a search and replace based on the following character. Use word boundaries

From :h \<:

                            */\<*
\<  Matches the beginning of a word: The next char is the first char of a
    word.  The 'iskeyword' option specifies what is a word character.
    |/zero-width|

                            */\>*
\>  Matches the end of a word: The previous char is the last char of a
    word.  The 'iskeyword' option specifies what is a word character.
    |/zero-width|

So :%s/\<in\>/& /g will do what you're looking for. (The ampersand means "the full text you matched", which is just "in")

The reason why your search wasn't found is because you can never match / \>/ because that means a space, followed by the end of a word. And "end of word" means The previous char is the last char of a word, i.e. not a space.

If you wanted to do something like match in not followed by t, you'd want something like int\@!, but lookaheads and lookbehinds are fairly complicated. I try to avoid them where possible. Although in this particular case, you know that in will be followed by a space, so something like:

:%s/in /&   /g

would work.


EDIT

:%s/\<in\>\s*/in    /g

will insure that running this substitution multiple times will not continually add spaces.

2
  • This is 90% there. I would like to place this in a function that is formatting a file so it may be run multiple times. Your solution as is would keep adding more spaces every time it is run. That's why I was thinking about the lookahead. Basically your solution making sure that after in it isn't followed by ` *` where * is any character... Does that make sense? Mar 8, 2019 at 18:21
  • 1
    @gutelfuldead That would have been useful information. I'm not 100% sure what you mean, but I added a new version that should fix that particular problem.
    – DJMcMayhem
    Mar 8, 2019 at 18:44
0

You don't need the word boundary start. Just replace the word boundary end for the match end flag:

:s/: in \ze[^ ]/& /g

You can use\zs for the match start flag as well.

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.