How can I autoformat/indent C code in vim? - c

When I copy code from another file, the formatting is messed up, like this:
fun()
{
for(...)
{
for(...)
{
if(...)
{
}
}
}
}
How can I autoformat this code in vim?

Try the following keystrokes:
gg=G
Explanation: gg goes to the top of the file, = is a command to fix the indentation and G tells it to perform the operation to the end of the file.

I like to use the program Artistic Style. According to their website:
Artistic Style is a source code indenter, formatter, and beautifier for the C, C++, C# and Java programming languages.
It runs in Window, Linux and Mac. It will do things like indenting, replacing tabs with spaces or vice-versa, putting spaces around operations however you like (converting if(x<2) to if ( x<2 ) if that's how you like it), putting braces on the same line as function definitions, or moving them to the line below, etc. All the options are controlled by command line parameters.
In order to use it in vim, just set the formatprg option to it, and then use the gq command. So, for example, I have in my .vimrc:
autocmd BufNewFile,BufRead *.cpp set formatprg=astyle\ -T4pb
so that whenever I open a .cpp file, formatprg is set with the options I like. Then, I can type gg to go to the top of the file, and gqG to format the entire file according to my standards. If I only need to reformat a single function, I can go to the top of the function, then type gq][ and it will reformat just that function.
The options I have for astyle, -T4pb, are just my preferences. You can look through their docs, and change the options to have it format the code however you like.
Here's a demo. Before astyle:
int main(){if(x<2){x=3;}}
float test()
{
if(x<2)
x=3;
}
After astyle (gggqG):
int main()
{
if (x < 2)
{
x = 3;
}
}
float test()
{
if (x < 2)
x = 3;
}

The builtin command for properly indenting the code has already been mentioned (gg=G). If you want to beautify the code, you'll need to use an external application like indent. Since % denotes the current file in ex mode, you can use it like this:
:!indent %

I find that clang-format works well.
There are some example keybindings in the clang documentation
I prefer to use the equalprg binding in vim. This allows you to invoke clang-format with G=gg or other = indent options.
Just put the following in your .vimrc file:
autocmd FileType c,cpp setlocal equalprg=clang-format

The plugin vim-autoformat lets you format your buffer (or buffer selections) with a single command: https://github.com/vim-autoformat/vim-autoformat. It uses external format programs for that, with a fallback to vim's indentation functionality.

I like indent as mentioned above, but most often I want to format only a small section of the file that I'm working on. Since indent can take code from stdin, its really simple:
Select the block of code you want to format with V or the like.
Format by typing :!indent.
astyle takes stdin too, so you can use the same trick there.

I wanted to add, that in order to prevent it from being messed up in the first place you can type :set paste before pasting. After pasting, you can type :set nopaste for things like js-beautify and indenting to work again.

Maybe you can try the followings
$indent -kr -i8 *.c
Hope it's useful for you!

Their is a tool called indent. You can download it with apt-get install indent, then run indent my_program.c.

For a good overview and demo of many of the options mentioned here, #Gavin-Freeborn has a great video on YouTube:
https://www.youtube.com/watch?v=tM_uIwSucPU
It covers some Vim plugins as well as built-in capabilities such as =, gq, and formatprg.

Related

Convert a Regular C styled coding file to GNU style coding standards

I have a file which I have written in "Regular C style". for example
void foo()
{
if(;;) {
....
} else {
...
}
}
wanted to change this style to GNU style coding using vim or some other plugin
void foo()
{
if(;;)
{
....
}
else
{
....
}
}
Wanted to ask if there can be a quick shortcut to do it so that it detects the loops starting braces and brings it below and indents it by 2 spaces.
Any help is greatly appreciated !
The correct tool for that job is GNU indent, which was created exactly for the purpose of re-indenting existing C code. In particular, you might want to look at the option --gnu-style.
Just a quick answer, probably not the best: you can insert the line breaks, select the whole document and re-indent with:
:1,$s/\v(\S) *\{/\1^M{/g
:1,$s/\v\} *(\S)/}^M\1/g
:1
VG=
Of course, this depends on your vim configuration (the = command, for instance, depends on your definition of equalprg). Moreover, this treats the comments like normal code.

Retrieving Global Variable Values from Command Line

In one particular project, we're trying to embed version information into shared object files. We'd like to be able to use some standard linux tool to parse the shared object to determine the version for automated testing.
Currently I have "const int plugin_version = 14;". I can use 'nm' and 'objdump' and verify that it's there:
00000000000dcfbc r plugin_version
I can't, however, seem to be able to get the value of that variable easily from command line. I figured there'd be a POSIX tool for showing the initialized values for globals. I have contemplated using a format for the variable as the information itself, ie, plugin_version_14, but that seems like a huge hack. Embedding the information in the filename unfortunately is NOT an option. Any other suggestions welcome.
You could embed it as a string
"MAGIC MARKER STRING VERSION: 4.56 END OF MAGIC" then just look for "MAGIC MARKER STRING" in the file and extract the version information that comes after it.
if you make it a standard, you could easily make command line tool to find these embeded strings on all your software.
if you require it also to be an int, a little macro magic will construct both the int and magic string to make sure they are never out of synch.
There's a couple of options I think.
My first instinct is to make sure the version information lives in its own section in the ELF file. You can use objdump -s -j name of section /bin/whatever.
This rather relies on objdump being available of course.
Alternatively you can do what Keith suggested, and just use 'strings', along with a magical marker string. This feels a little hackish, but should work quite well.
Finally, why don't you just add a --version command line option? You can then store the version information however you like, and trivially retrieve it using the one tool which is certain to be installed on any system which has your software.
A terrible hack that I've used in the past is to embed the version information in a variable name, so nm will show:
00000000000dcfbc r plugin_version_14
Why not writing your own tool to get that version in C/C++ ? You could Use dlopen, then dlsym to get the symbol and print its value to standard output. This way you also verify if the symbol is already there. It looks like 20 ~ 30 lines of code to me and about 20 minutes of your life :)
I know that the question is about command line, but writing such a tool yourself should be easy (especially if such a command line tool does not exist).
If the binary is not stripped, you could use gdb to print the variable. (I just tried to script gdb, but it seems to refuse work if stdin is not a tty, maybe expect will do the job ? )
If you can accept using python, this might help:
import struct
import sys
import subprocess
if __name__ == '__main__':
so = sys.argv[1]
sym = sys.argv[2]
addr = subprocess.check_output('nm %s | grep %s' % (so, sym), shell=True)
addr = int(addr.split()[0], 16)
so_file = open(so)
so_file.seek(addr)
data = so_file.read(4)
print struct.unpack('#i', data)[0]
Disclaimer: This script doesn't do any error checking (if you like it I'm sure you can come up with some ;)). It also assumes you're reading a 4-byte native int value.
$ cat global.c
const int plugin_version = 14;
$ python readsym.py global.so plugin_version
14

Format of structs using emacs c code auto-newline

I have recently started using emacs for editing C source, and have been using the auto-newline feature of cc-mode (c-toggle-auto-newline). This works well for constructs like functions and if/else statements, but seems to act strangely when a closing brace should be followed by a semi-colon.
Using auto-newline in GNU Emacs 23.3 I get:
struct foo
{
int x;
}
;
char int[2] =
{
0, 1
}
;
I would like to instead get:
struct foo {
int x;
};
char int[2] = { 0, 1 };
How can I get the closing semi-colon to remain on the same line as the closing brace?
I don't think you can go around this problem with auto newline on. It's not a greatly thought-through feature, it simply inserts newlines after certain characters (;, {, etc.). But seriously, how hard is it to press and enter key? Any automation is always error-prone.
You can customize the "cleanup" behavior when auto-newline is turned on. This is controlled by the contents of the c-cleanup-list variable. (View help for this within Emacs by entering C-h v c-cleanup-list.
Specifically, adding defun-close-semi to c-cleanup-list will solve your problem.
If you're already defining a custom style within your ~/.emacs file, then you can probably figure out how to do this. Otherwise, the easiest way to change this setting is via Customize. In the help buffer (displayed when you ran C-h v c-cleanup-list), the last line will have a link to customize this variable.

Condense multiline C function prototypes

I have C function prototypes (certain windows api header files) that look like:
int
foo
(
int
a
,
int
*
b
)
;
(they seem to have no coding convention)
which I am trying to programmatically turn into a one-line prototype of the form (or something close to it):
int foo(int a, int * b);
I have looked into programs like ctags ( ctags multi-line C function prototypes ) and into various settings in uncrustify ( http://uncrustify.sourceforge.net/ ) however I haven't been able to make any headway in either. (any insight would be great, or perhaps one of the 385 uncrustify options that I missed does what I want).
Programmatically, I am trying to look for unique markers that signify a function prototype so that I can write a script that will format the code to my liking.
Without using a lexer and a parser this seems like it could get very convoluted very quickly; any suggestions?
run them through indent -kr or astyle --style=kr
Solution using vim?
put marker on int and do 11J
sed ':a;N;$!ba;s/\n/ /g' prototypes.file | sed 's/; */;\n/g'
The first command - before the pipe - will replace all new-lines to spaces, and the next will put a new-line back after every semicolon.
Of course this will only work if there are nothing else but these prototypes in the file. If there are some other stuff that you want to keep as they are, you can use vim's visual selection and two substitution commands:
Select the region you want to join, than
:s/\n/ /
Select the joined line and
:s/; */;\r/g
Another solution using vi:
do a regex search removing all newlines. Then take the resulting mess and do another regex search replacing each ; with ; \n\n. That should leave you with a list of prototypes with a line skipped between each one. Since we're marking the ends of the prototypes instead of the beginnings and all prototypes end the same way, we don't have to worry about not recognizing special cases.

Emacs comment-region in C mode

In GNU Emacs, is there a good way to change the comment-region command in C mode from
/* This is a comment which extends */
/* over more than one line in C. */
to
/* This is a comment which extends
over more than one line in C. */
? I have tried
(setq comment-multi-line t)
but this does not help. There is a section on multi-line comments in the Emacs manual, but it does not mention anything.
Since Emacs 21, there's been a module named 'newcomment, which has different comment styles (see the variable 'comment-styles. This setting gets close to what you want:
(setq comment-style 'multi-line)
(Note: you should probably make that setting in 'c-mode-hook).
However, none of the settings make the comments look like what you want.
The easiest way I saw to get what you want is to add this hack:
(defadvice comment-region-internal (before comment-region-internal-hack-ccs activate)
"override 4th argument to be just spaces"
(when (eq major-mode 'c-mode) ; some condition here
(let ((arg (ad-get-arg 4)))
(when arg
(ad-set-arg 4 (make-string (length arg) ?\ ))))))
The current settings for comment-style always prefix the comment lines with " * " (if not the whole " /* ").
If you don't have Emacs 21, I suppose you could simply download newcomment.el from the repository. I don't know if it works as-is in earlier versions of Emacs, but it might be worth a shot, though upgrading Emacs would be a better solution.
My hack breaks the 'uncomment-region. A proper fix would be to change 'comment-padright. That would take a little more research so as not to break other things. The above hack only changes behavior in 'c-mode (adjust the condition to your liking).
Closest I could find with the built-in commenting support is if you set comment-style to multi-line, which will produce this:
/* This is a comment which extends
* over more than one line in C. */
If that isn't close enough, take a look at newcomment.el and define your own commenting functions as appropriate.

Resources