how to add a condition when searching in VIM? - search

how to add a condition when searching in VIM?
input:
int myFoo(int) ;
int myFoo ( int) ;
int myFoo ( int );
int myFoo ( int );
output:
int myFoo ( int );
int myFoo ( int );
int myFoo ( int );
int myFoo ( int );
how do I do the search and replace correctly?
I can do the usual search and replace.
:g/ *(/s//\ (/g
:g/( */s//\( /g
:g/ *)/s//\ )/g
:g/) */s//\)/g
But is there an easier way?

What does "easier" mean, here? Do you find your current solution difficult?
It is overcomplicated, that's for sure, as you don't need :help :global to begin with. So you can make it simpler:
:%s/ *(/\ (/g
:%s/( */\( /g
:%/s/ *)/\ )/g
:%s/) */\)/g
And you can simplify it further by removing the g flag because there is only one match on each line:
:%s/ *(/\ (
:%s/( */\( /
:%/s/ *)/\ )
:%s/) */\)
It is also possible to do it all with a single substitution:
:%s/ *( *\(\S*\) *) */( \1 )
but I am not sure that qualifies as "easier".
The better way would be to let some external formatter (set via :help 'formatprg') deal with the problem via a simple gq<motion>.

Related

How can I line up/indent function arguments up to (

I want to do this in VIM:
// before
int DoStuffToSometing(int stuff,
char action,
int something);
// after
int DoStuffToSometing(int stuff,
char action,
int someting);
=% while being on the matching parenthesis, doesn't work.
How to line up things as shown above?
Use :set cinoptions+=(0 then do the select the content and press =.

Error: this declaration has no storage class or type specifier ( Me making a simple struct. )

I was trying to make a simple struct to hold character stats.
This is what I came up with:
struct cStats
{
int nStrength;
int nIntelligence;
int nMedical;
int nSpeech;
int nAim;
};
cStats mainchar;
mainchar.nStrength = 10;
mainchar.nIntelligence = 10;
mainchar.nMedical = 10;
mainchar.nSpeech = 10;
mainchar.nAim = 10;
The mainchar. part is underlined red in visual studio, and when I mouse over it it shows this:
Error: this declaration has no storage class or type specifier
Any explanation of why it's doing this, and what I should be doing to fix it would be appreciated.
If this is C you should tag your question as such. cStats is a structure tag, not a type specifier. You need to declare mainchar as:
struct cStats mainchar;
If you wanted to use cStats as a type specifier you would define it as:
typedef struct
{
int nStrength;
int nIntelligence;
int nMedical;
int nSpeech;
int nAim;
} cStats;
If you did that your cStats mainchar would work.
Note that in C, char and character mean “ASCII alphanumeric character”, not “character in a play or game”. I suggest coming up with a different term for your program.
Another bit of advice; do not prefix your names with their data type; like nStrength for integer Strength. The compiler will tell you if you get your data types wrong, and if you ever need to change a type, for example to float nStrength to handle fractional Strengths, changing the name will be a big problem.
main(){
mainchar.nStrength = 10;
mainchar.nIntelligence = 10;
mainchar.nMedical = 10;
mainchar.nSpeech = 10;
mainchar.nAim = 10;}
These initialization should be written within the main() function.
Or else, write a init function and call it from main function.

Is there a way to change the way vim auto formats c,c++ code

For example --
when i do gg=G on
int main()
{
return 0;
}
it will change it to
int main()
{
return 0;
}
What I want is --
int main(){
return 0;
}
The '{' should be on the funciton prototype line
AFAIK:
= re-adjusts indent, it doesn't reformat your codes' style. e.g, the code block style (your question); or add/removing empty lines; add/remove spaces e.g. a=2 -> a = 2 ...
you could do this to change the { before/after you gg=G:
:%s/)\n\s*{\s*$/) {/g
you could also write them into one line, and make a mapping to do it in one short.
e.g, this line:
:%s/)\n\s*{\s*$/) {/g|norm! gg=G
will turn:
int main()
{
if(foo)
{
return 1;
}
if(a>0)
return a;
for(int i=1;i<20;i++)
{
int foo=0;
foo=i;
}
return 0;
}
into
int main() {
if(foo) {
return 1;
}
if(a>0)
return a;
for(int i=1;i<20;i++) {
int foo=0;
foo=i;
}
return 0;
}
EDIT
My original answer suggested :g/)$/j to "join" the two lines, but I found it is not safe, for example:
if (a>0)
return a;
will be turned into
if (a>0) return a;
which is not expected by OP.
To go along with Cubic's Answer
To use astyle without modifying file you can use the command gq and the option `formatprg'
formatprg specifies an external program that will be used to format the buffer. After the command has been run the buffer will be replaced by the output of the program.
For exmample: To set this to work with c files you can put the following in your vimdc
autocmd FileType *.c set formatprg=astyle\ --style=kr
Note: the \ allows you to pass the different command line options to style.
Now to use this in your file you can type gggqG to apply the formatting to the whole file.
You could use astyle, with something like
nnoremap <A-S-f> :w<CR>:!astyle % --style=java<CR>:edit<CR>
Which binds it to Alt-Shift-f (note that this saves/reloads the file which may not always be what you want, there are ways around that but I didn't want to go too much into this right now).
Of course, you'll have to figure out what options to pass to astyle for your preferred formatting yourself.

error C2440: '=' : cannot convert from 'const char *' to 'char *'

I've spent many hours on here looking for help on what is apparently a common error but none that I've seen seems to fit my case.
I am migrating a old out sourced program that was written in Visual Studio 6 C++ to Visual Studio 2012 and fortunately for me as I'm not a C++ programmer (just a lowly VB and C# developer). The migration wizard and the internet have been a great help in helping me find and correct code that the wizard can't handle.
In this code block which I believe is doing nothing more than creating a directory
int CreateAllDirectories(const char* pszDir)
{
char* pszLastSlash;
char cTmp;
if( _access( pszDir, 0 ) != -1 ) {
// it already exists
return 0;
}
pszLastSlash = strrchr( pszDir, '\\' );
if ( pszLastSlash ) {
cTmp = *pszLastSlash;
*pszLastSlash = '\0';
// try again with one less dir
CreateAllDirectories( pszDir );
*pszLastSlash = cTmp;
}
if ( _mkdir( pszDir ) == -1 ) {
return -1;
}
return 0;
}
an error generates when the results of strrchr( pszDir, '\' ) are assigned to the variable pszLastSlash. From the rest of this code it looks like pszLastSlash = strrchr( pszDir, '\' ); is a valid expression.
Is the issue with the double backslash which to me looks like and escape sequence.
Maybe in this line...
pszLastSlash = strrchr( pszDir, '\\' );
pszLastSlash is not constant but pszDir is constant. There are two defs for strrchr() (see http://www.cplusplus.com/reference/cstring/strchr/)...
const char * strchr ( const char * str, int character );
char * strchr ( char * str, int character );
Because you input a constant char *, it will try to use the def that returns a const char*, but you're assigning it to a non-const char*. I think that is what is generating your error.
Because pszDir is const, the pointer returned to you is const because you shouldn't be modifying the area of memory pointed to by pszDir.
If you have allocated pszDir yourself, and you know it is safe to modify, your could relax your const contraint in the function def? I.e.,
int CreateAllDirectories(char* pszDir)
But, only do this is pszDir is a string that you own and can modify :)
I just noticed in the C++ reference page that...
In C, this function is only declared as:
char * strchr ( const char *, int );
So, if you previously used C, then that would explain why you see the error now.
Since this line
*pszLastSlash = '\0';
is modifying the buffer passed into your function, you must not promise your caller that you won't modify the buffer. Therefore
int CreateAllDirectories(char* pszDir);
is the correct signature
You can try putting new in the middle of
pszLastSlash = strrchr( pszDir, '\' );
So, it will be
:pszLastSlash = new strrchr( pszDir, '\' );

aligning text in vim according to whitespace using tabularize plugin

I'm trying to align the following text in vim using tabularize:
typedef struct {
int a;
int *pa;
float b;
float *pb;
double c;
double *pc;
} foo_t;
to this:
typedef struct {
int a;
int *pa;
float b;
float *pb;
double c; /* notice there's only one space between 'double' and 'c' */
double *pc;
} foo_t;
I tried using :'<,'>Tab/.*\s but it leaves two spaces between double and c. How can I do this?
You can use this command:
:'<,'>Tabularize /\S\+;$/l1
/\S\+;$/ pattern: make a;,*pa;...*pc; as column separators.
l1 flag: make every column left alignment and one space after it. (Not required here, because it's a default behavior)

Resources