It has been a while since I wrote my last post. Sorry for the delay, but I was a bit busy lately. In this post, I shall explain how to get the most of your nautilus file manager by using shell scripts.
Nautilus provides some facilities available from shell scripts. Combining them with a small utility called zenity can improve your daily tasks.
Nautilus has the ability of executing shell scripts applying them to the selected files. The executable scripts are those present in the following directory:
~/.gnome2/nautilus-scripts
Every script present in that directory will be shown in the “Scripts” entry of the contextual menu that shows up by right-clicking on a file. If that entry is not shown, navigate into the directory mentioned above in Nautilus and you will see a message indicating that all the scripts in the folder will be available from now on.
Nautilus sets up four environment variables for the process executing the script which are:
NAUTILUS_SCRIPT_SELECTED_FILE_PATHS: selected file paths.
NAUTILUS_SCRIPT_SELECTED_URIS: URIs delimited by \n
NAUTILUS_SCRIPT_CURRENT_URI: Current URI
NAUTILUS_SCRIPT_WINDOW_GEOMETRY: size and location of the current window
In addition, the names (without the full path) of all the selected items are passed to the script as input parameters.
These scripts will be executed silently (not in a terminal window) so it seems reasonable to be able to communicate with the user. Enter zenity.
Introducing zenity
zenity is a program for displaying GTK+ dialogs. It reads data from stdin and returns user input through stdou. It is an easy way of gathering and showing information from a shell script on a desktop environment. Here are some examples on how to use zenity:
Show an information window:
$ zenity --info --title=InfoWindow --text="This is an information text"
Get some user input:
$zenity --entry --title=EntryWindow --text="Type a text, please"
Hello World!
$
As you can see, zenity provides an easy way to interact with the user in a graphical environment.
With this little information, it is possible to write a small debugging script. I called it test.sh
#! /bin/bash
# Use /usr/local/bin/bash on FreeBSD
ZENITY=$(which zenity)
$ZENITY --info --text="$*"
$ZENITY --info --text="NAUTILUS_SCRIPT_SELECTED_FILE_PATHS = $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS"
$ZENITY --info --text="NAUTILUS_SCRIPT_SELECTED_URIS = $NAUTILUS_SCRIPT_SELECTED_URIS"
$ZENITY --info --text="NAUTILUS_SCRIPT_CURRENT_URI = $NAUTILUS_SCRIPT_CURRENT_URI"
$ZENITY --info --text="NAUTILUS_SCRIPT_WINDOW_GEOMETRY = $NAUTILUS_SCRIPT_WINDOW_GEOMETRY"
This script shows the contents of the parameters and the Nautilus variables.
zenity is really easy to use, and with a little effort and some bash scripting knowledge (that I will not explain, because it is out of the scope of this post) you can write a convenience script like the one below (I named it packit.sh):
#! /bin/bash
# Use /usr/local/bin/bash on FreeBSD
#
# Small script intended to be used from Nautilus.
# It compresses the selected files and/or directories
# in several formats
# Requires: zenity, tar, gzip, bzip2, zip, mkisofs
FORMATS="tar tgz tbz2 zip iso9660"
ZENITY=$(which zenity)
# Check if we have selected any files...
if [ -z "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS" ]; then
$ZENITY --error --text="No files selected"
exit 0;
fi
# Ask for output file name
output_filename=packit-$(date +%s)
output_filename=$($ZENITY --entry --title="Output file name" --text="Type file name" --entry-text="$output_filename")
# Ask the user to select a compressing format
selected_format=$($ZENITY --title="Select format" --list --column=Format $FORMATS)
if [ -z "$selected_format" ]; then
$ZENITY --error --text="No format selected"
exit 0;
fi
# Select the compressing utility to use
case $selected_format in
"tar")
COMP_COMMAND="tar cvf"
;;
"tgz")
COMP_COMMAND="tar czvf"
;;
"tbz2")
COMP_COMMAND="tar cjvf"
;;
"zip")
COMP_COMMAND="zip -9"
;;
"iso9660")
COMP_COMMAND="mkisofs -R -o"
;;
esac
# Execute the command while showing a progress bar.
(echo "0" ;
$COMP_COMMAND "$output_filename" $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS
echo "100") | $ZENITY --progress --pulsate --title=Working...
The script above works for me, but it assumes the existence of several commands. If you want to use it you might need modify some lines.
Enjoy!
I know, running fsck on a mounted filesystem is utterly unrecommended. The command warns you (it actually frightens you) with the following message:
# fsck /dev/VolGroup00/LogVol00
fsck 1.41.4 (27-Jan-2009)
e2fsck 1.41.4 (27-Jan-2009)
/dev/VolGroup00/LogVol00 is mounted.
WARNING!!! Running e2fsck on a mounted filesystem may cause
SEVERE filesystem damage.
Do you really want to continue (y/n)? no
check aborted.
But sometimes I need to check a filesystem in a remote host, so I cannot boot from a liveCD to run fsck in the unmounted device. Looking for an option allowing me to overcome this nuisance I found the following in e2fsck’s man page:
Note that in general it is not safe to run e2fsck on mounted filesys-
tems. The only exception is if the -n option is specified, and -c, -l,
or -L options are not specified.
Using e2fsck instead of fsck is not a problem because it checks ext2 and ext3 filesystems and mine are ext3 (fsck checks and optionally repairs a lot of filesystem types).
Let us see what the man page says about the -n option:
-n Open the filesystem read-only, and assume an answer of `no' to
all questions. Allows e2fsck to be used non-interactively.
(Note: if the -c, -l, or -L options are specified in addition to
the -n option, then the filesystem will be opened read-write, to
permit the bad-blocks list to be updated. However, no other
changes will be made to the filesystem.) This option may not be
specified at the same time as the -p or -y options.
So it seems to be safe running it with that option. But the e2fsck man page also states (dealing with the safe check):
However, even if it is safe to do
so, the results printed by e2fsck are not valid if the filesystem is
mounted. If e2fsck asks whether or not you should check a filesystem
which is mounted, the only correct answer is ``no''. Only experts who
really know what they are doing should consider answering this question
in any other way.
So, I use it only when I want to know if there is something wrong with the filesystem. I run it with the -f option too which forces checking even if the file system seems clean.
# e2fsck -fn /dev/VolGroup00/LogVol00
e2fsck 1.41.4 (27-Jan-2009)
Warning! /dev/VolGroup00/LogVol00 is mounted.
Warning: skipping journal recovery because doing a read-only filesystem check.
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
F10-i686-Live: 123335/475136 files (3.8% non-contiguous), 876070/1900544 blocks
If the output is like above all is OK, but if the device has errors, then you will need to run fsck with the filesystem unmounted.
# touch /forcefsck
Creating an empty
forcefsck file in the root directoy will force
fsck to run at the next boot.
Welcome to the last “Vim for programmers” issue. Ironically, in this issue I will show you some nice characteristics despite they are not specific of programming. However they make much more sense when they are applied to programming.
Getting C help
This first feature is oriented directly to C programming. In most UNIX systems, there is a collection of system manual pages available with the command “man”. Although I will not explain man in detail (you can read more here (or type man man) it is worth saying it shows information about the command, system call, file, etc passed as parameter. In the simplest case it works this way:
$ man scanf
How is this related to Vim? Vim allows contextual access to the system manual using the K command. For example, given the code below:
#include
int main(int argc, char **argv)
{
printf("Hello world);
}
We can place the cursor at the “printf” function call and press K.
However, the information showed by man relates to the printf user command. At this point, it is necessary to explain that the system manual is split into several sections (man man for more information). To query the manual about a specific section, we need to pass the section number as first parameter, e.g:
$ man read # Section 1, shows read /bin/sh built-in command.
$ man 2 read # Section 2, shows read system call.
Going back to our example, if we want to see the manual page on the printf C function (Section 3 “System library calls”) we need to type 3K. Once you are done with the manual, type ENTER to return to Vim.
This is an extremely useful feature (unless you have memorized all the functions / system calls present in your system)
Folding
Folding is just great. It is a feature that lets you “compress” several lines into a single one which is useful to compress function bodies for instance. The fold can be opened and closed at will. To create a fold, type “zf”. But first, you have to instruct Vim which lines to include. You can do this
in several ways (repetition, selecting the lines in visual mode, etc):
void simple_function(void)
{
int i;
int j;
float f;
return;
}
If we want to fold the variable declaration section and the cursor is placed at the first variable declaration line, we can do the following: “zf2j”.
This tells Vim to create a fold and include the current line and the next two. The same thing can be done with “Vjjzf”. In this case, we go to visual mode, move two lines downwards and create the fold. In both cases, we end up with the following:
void simple_function(void)
{
+-- 3 lines: int i;-------------------------------------------------------------------------------------------
return;
}
Vim replaces the selected lines with a single one. This line has a leading ‘+’ character and shows the first folded line as a reminder for the user. Placing the cursor at that line we can operate with the fold. We can either open it (zo) or close it (zc). These two operations can be applied at every line inside the fold.
Folds behave as other text objects in most aspects. You can cut a fold and paste it elsewhere, however, when you paste it, the fold is destroyed (hold your horses, I said the fold, but your text is still there). If you undo (u) the copy-paste operation, the fold does not come back. If you make a copy, the fold persists, and the new text (wherever you paste it) is pasted unfolded.
Folds can be nested, as in the example below:
int main(int argc, char **argv)
{
int var1;
int var2;
float var3;
struct person {
unsigned int salary;
unsigned char siblings;
char *name;
};
struct person john;
return 0;
}
First, we collapse the struct person
int main(int argc, char **argv)
{
int var1;
int var2;
float var3;
+--- 5 lines: struct person {---------------------------------------------------------------------------------
struct person john;
return 0;
}
And then, we compress everything but the return statement.
int main(int argc, char **argv)
{
+-- 11 lines: int
var1;----------------------------------------------------------------------
return 0;
}
If we unfold the top level fold, the inner one is shown collapsed. The states of nested folds are independent. zd and zD are used to deleted folds (the latter recursively), and zE deletes all the folds in the current window. As a general rule, the capitalized version of all the commands (zC, zO) applies the action recursively.
Marks
The name speaks by itself. Marks allow you to refer to a location in a file, using a name. I make an intensive use of marks, because often, I need to jump from one place to another in the code. Let us see how to use them playing with a small text:
This is the first line
This is a second line
And finally, this is the last line
The cursor is placed at the “r” in boldface in the first line. We use the m command followed by the letter (the identifier) of the mark to create a new mark. For instance ma creates a mark called a. Marks are not shown in Vim in any way, they just exist :)
Once the mark is set, you can jump to it using either ‘ or ` followed by the mark identifier. The single quote jumps to the beginning of the line (the T letter) and the backtick jumps to the specific location of the mark (the r letter). The :delmarks command deletes the specified mark and :marks shows all the marks.
There are two kind of mark identifiers:
- a - z. Valid within a file as long as it is loaded in a buffer
- A - Z. Valid between files.
When using upper case letters as identifiers, Vim loads the required file if necessary.
Note: There is another kind of mark identifiers (0 - 9) but they are out of the scope of this post.
Marks are specially useful for jumping between two or more functions or locations in your code.
Undo branches
This is a complex topic and I will just introduce it. For more information, see :help new-undo-branches on a Vim 7 editor.
Vim supports undo branches. This means Vim can keep track of the different changes you made to your text (or your code). In its simplest form, you can use two commands, :earlier and :later to bring your code to a previous state. E.g:
:earlier 20s
:later 5m
:earlier 2h
The commands above bring the code to the state it was 20 seconds earlier, 5 minutes later and 2 hours later.
This is useful when making changes to code under no source control systems. Undo branches is a new feature present in Vim since version 7. I recommend you to play with it and learn how to get the maximum out of it.
Vim Sheet (VI)
- [number]K. Show manual page for the word under the cursor.
- zf. Create a fold.
- zo / zc Open / close a fold.
- zd Delete a fold.
- zE Delete all the folds in a file.
- m[identifier] Creates a mark
- ‘[identifier] Goes to the first non-blank character of the line where the mark is located
- `[identifier] The same as above but move to the precise location of the mark.
- :marks Show all the marks
- :delmarks Delete a mark.
- :earlier [s/m/h] Brings the text to an earlier state
- :later [s/m/h] Brings the text to a later state from a past point in the undo branch.
rpm is a powerful Package Manager, which can be used to build, install, query, verify, update and erase individual software packages. It is the default package manager for several popular distributions such as Red Hat, Fedora, Suse and many others.
The list of dependencies an rpm package has, that is, the packages that must be installed in the system for it to work properly, can be shown with the following command if the argument is the rpm file:
# rpm -qpR rsync-3.0.6-0.fc10.i386.rpm
config(rsync) = 3.0.6-0.fc10
libacl.so.1
libacl.so.1(ACL_1.0)
libc.so.6
libc.so.6(GLIBC_2.0)
libc.so.6(GLIBC_2.1)
libc.so.6(GLIBC_2.2)
libc.so.6(GLIBC_2.3)
libc.so.6(GLIBC_2.3.4)
libc.so.6(GLIBC_2.4)
libc.so.6(GLIBC_2.8)
libpopt.so.0
libpopt.so.0(LIBPOPT_0)
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rtld(GNU_HASH)
and this command if querying on the package name:
# rpm -qR rsync
config(rsync) = 3.0.6-0.fc10
libacl.so.1
libacl.so.1(ACL_1.0)
libc.so.6
libc.so.6(GLIBC_2.0)
libc.so.6(GLIBC_2.1)
libc.so.6(GLIBC_2.2)
libc.so.6(GLIBC_2.3)
libc.so.6(GLIBC_2.3.4)
libc.so.6(GLIBC_2.4)
libc.so.6(GLIBC_2.8)
libpopt.so.0
libpopt.so.0(LIBPOPT_0)
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rtld(GNU_HASH)
In the first part of this series, we visited some Vim features that help us in programming. In this second issue, I will show you some other important things you should know to really appreciate the power of Vim.
Completion
Completion is not a programming specific feature in Vim, however it is in programming where I find it to be more useful. There are several completion options, but I will explain the ones I find more interesting. Completion is a sub mode of insert mode. This means the commands are applied while being in insert mode.
- Line completion: Ctrl-x Ctrl-l completes the whole line. This is very useful as in programming, yo usually need to write exactly the same line you wrote before or a line very similar to that one.
- Word completion: Ctrl-p completes a word
- File completion: Ctrl-x Ctrl-f Extremely useful in #include like sentences as it completes file names.
Tags
Tags are a used to rapidly navigate source code. Having the cursor placed at a function invocation, it lets you jump to the function definition. Vim has support for tags based on the ctags utility. Ctags scans your source files and creates an index file with information about the structures and objects found in the code. Vim uses this file to know about your source code (functions, variables, etc.)
The first step is to run ctags. Change to the top level source directory of your project and run the following command:
$ ctags -R
This runs ctags recursively in all directories. Note that the BSD ctags version does not provide this flag, so it could be convenient to install the GNU version from ports (/usr/ports/devel/ctags) that gets named exctags upon installation.
Ctags just creates a “tags” file we can inspect (it is a text file):
$ less tags
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.5.4 //
__UTILS_H__ utils.h 2;" d
main main.c /^int main(int argc, char **argv)$/;" f
multiply utils.c /^int multiply(const int a, const int b)$/;" f
Vim uses a tags file in the current directory if present, but it can be instructed to load an alternative one using the -t flag:
$ vim -t /path/to/tags_file
Let us create a project with three files:
$ cat main.c
#include "utils.h"
int main(int argc, char **argv)
{
int result;
resultxx = multiply(3, 4); /* resultxx is not defined */
printf("Result = %d\n", result) /* ; missing */
retrun 0; /* this should be 'return' */
}
$ cat utils.c
int multiply(const int a, const int b)
{
return a * b;
}
$ cat utils.h
#ifndef __UTILS_H__
#define __UTILS_H__
int multiply(const int a, const int b);
#endif /* __UTILS_H__ */
After running ctags * (we do not need the -R flag in this example) if we place the cursor at the ‘multiply’ invocation and press Ctrl-], we jump to the function’s code. Once there, we can go back using Ctrl-t. Vim stacks the jumps so you can move forward / backwards using these commands no matter how deep you go into your code. At any time, you can check the state of the stack with:
:tags
# TO tag FROM line in file/text
1 1 multiply 8 main.c
>
Finding the declaration
The embedded gD command applied on a variable or function name moves the cursor to the declaration of that variable / function. If the prototype of the function does not exist, then it takes the cursor to the definition of the function.
Omni completion
This is known by Microsoft as “Intellisense”. It basically autocompletes in an intelligent way. For instance, if you have something like this:
struct person {
char* name;
unsigned char children
unsigned char age;
};
struct person john;
Now, if you type john. and then Ctrl-X Ctrl-O, Vim will autocomplete with one of the fields of the struct. This would be in a perfect world, however this is not as easy. First off, omni completion is based on a ctags file. If you want a “full” C language completion, you need to first create a tags file scanning /usr/include, /usr/local/include and so on. In my laptop (AMD 64 900 MHz), executing this:
exctags -R -f ~/.vim/systags /usr/include /usr/local/include
takes almost 6 minutes and the generated file is as big as 791M. In addition if you install a new development library, you will need to scan the .h files to add them to you tags file. Personally I do not use omni completion as I do not think it is mature enough yet.
Compiling from inside Vim
Let us assume you are editing main.c from the project above. Usually, you would leave the editor and compile the sources by hand, typing commands in the shell. From inside Vim, you can do the same with:
$ :!gcc -Wall -o program main.c utils.c
But there is a more efficient mechanism to compile a project. This method implies the creation of a Makefile. Probably you should have a Makefile for all your projects as it improves compilation times and helps managing other tasks as installation. How to write a Makefile is out of the scope of this post, you can find more information here. Assuming you have created your Makefile, you can compile your project with:
:make
f00993z4@cipres:~/prueba/dummy> vim main.c
gcc -o program main.c utils.c
main.c: In function 'main':
main.c:8: error: 'resultxx' undeclared (first use in this function)
main.c:8: error: (Each undeclared identifier is reported only once
main.c:8: error: for each function it appears in.)
main.c:12: error: expected ';' before 'retrun'
make: *** [all] Error 1
Press ENTER or type command to continue
So far, the behavior is similar to the shell way. However, Vim parsed the output of the make command so you can see a list of errors directly from Vim:
:clist
3 main.c:8: error: 'resultxx' undeclared (first use in this function)
4 main.c:8: error: (Each undeclared identifier is reported only once
5 main.c:8: error: for each function it appears in.)
6 main.c:12: error: expected ';' before 'retrun'
Pulse INTRO o escriba una orden para continuar
The example above shows the output of make with the lines in which the errors occurred. In addition the messages are pretty nice formatted and colored ;)
After typing ENTER, Vim places the cursor at the line in which the first error occurred (line 8).
We fix the error (the name of the variable is wrong) and move on:
:cn
We have to do this several times because Vim shows you all of make’s output, so you have the whole description instead of just the first line of the error message (in this case, the error was pretty obvious, but in cases in which C++ and STL are involved, I really appreciate the complete message).
Finally, Vim places the cursor at other line:
(6 de 7): error: expected ';' before 'retrun'
We missed the ‘;’ at the previous line. We fix the error and move on:
:cn
There are no more errors. How is this possible if we did not fix the ‘retrun’ issue? It is because the compiler did not reach that point. It realized the ‘;’ was missing and after that it could not tell what the ‘retrun’ thing was about. This is how compilers work, we can not blame Vim for it :)
Let us compile again:
:make
gcc -o program main.c utils.c
main.c: In function 'main':
main.c:12: error: 'retrun' undeclared (first use in this function)
main.c:12: error: (Each undeclared identifier is reported only once
main.c:12: error: for each function it appears in.)
main.c:12: error: expected ';' before numeric constant
make: *** [all] Error 1
We fix the error, and compile for the last time:
:make
Press ENTER or type command to continue
gcc -o program main.c utils.c
Press ENTER or type command to continue
Here you are!, your project successfully compiled!.
I moved forward fixing a bug at a time, but you can use the :cp (cprevious) command to move to a previous error line.
Note that the :make command does not actually execute the ‘make’ program. It executes the program the variable makeprg is pointing to. In my BSD box, I usually do this:
:set makeprg=gmake
in order to use the GNU make version instead of the BSD licensed one.
Conclusion
Vim provides many features useful for programming. Completion is specially useful as Vim learns as you type. The other very useful thing is the possibility of executing Makefiles from inside the editor. The parsing of the output makes the edit-compile-debug cycle more efficient.
Vim Sheet (VI)
- Ctrl-x Ctrl-l / Ctrl-p / Ctrl-f Autocomplete the whole line / word / file name
- vim -t file_name Open Vim with the file_name tags file loaded.
- Ctrl-] / Ctrl-t Jump to the definition of that object / Jump back. (The objects must be scanned and present in the tags file)
- gD Go to the declaration / definition of the variable / function name
- :make Execute make in the current directory
- :clist Show the error and warning list
- :cn / :cp Move to the next / previous error line.
In FreeBSD:
$ cd /usr/src
$ make love
Enjoy the output. Merry Christmas!
Source:
psybermonkey
A file with the extension .dmg uses a proprietary disk image format commonly found on Mac OS X (well, usually: you can use any extension anywhere, obviously) .
The command used for manipulating disk images is hdiutil
$ hdiutil attach nmap-5.00.dmg
esperado CRC32 $C955C266
/dev/disk2 Apple_partition_scheme
/dev/disk2s1 Apple_partition_map
/dev/disk2s2 Apple_HFS /Volumes/nmap-5.00
This command will attach a disk image to the system as a device. attach will return information about an already-attached image if it had already attached it. mount is a synonym for attach.
$ hdiutil detach /Volumes/nmap-5.00/
"disk2" unmounted.
"disk2" ejected.
The above command will detach a disk image and terminate any associated hdid process. eject is a synonym for detach.
There are useful encryption options which we shall speak of in a forthcoming post.
Some days ago Google launched its public DNS service. Another older, public DNS service is OpenDNS. Both let you use their DNS servers insted of your ISP’s.
I have been using OpenDNS for a year because I had problems with my ISP’s DNS servers. They were down frequently, so I searched for a reliable alternative. There are some ways to know if your service provider’s DNS servers are working properly.
You can use nslookup, which is a program to query Internet domain name servers.
$ nslookup google.com
Server: 208.67.222.222
Address: 208.67.222.222#53
Non-authoritative answer:
Name: google.com
Address: 66.102.9.103
Name: google.com
Address: 66.102.9.105
Name: google.com
Address: 66.102.9.99
Name: google.com
Address: 66.102.9.104
Name: google.com
Address: 66.102.9.147
The host command is a simple utility for performing DNS lookups. It is normally used to convert names to IP addresses and vice versa.
$ host google.com
google.com has address 66.102.9.105
google.com has address 66.102.9.147
google.com has address 66.102.9.104
google.com has address 66.102.9.103
google.com has address 66.102.9.99
google.com mail is handled by 10 google.com.s9b2.psmtp.com.
google.com mail is handled by 10 google.com.s9a2.psmtp.com.
google.com mail is handled by 10 google.com.s9b1.psmtp.com.
google.com mail is handled by 10 google.com.s9a1.psmtp.com.
And finally, the dig command (domain information groper) is a flexible tool for querying DNS name servers. It performs DNS lookups and displays the answers returned from the queried name server(s). Most DNS administrators use dig to troubleshoot DNS problems because of its flexibility, ease of use and clarity of output.
$ dig google.com
; <<>> DiG 9.4.3-P3 <<>> google.com
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62217
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;google.com. IN A
;; ANSWER SECTION:
google.com. 141 IN A 66.102.9.103
google.com. 141 IN A 66.102.9.104
google.com. 141 IN A 66.102.9.105
google.com. 141 IN A 66.102.9.147
google.com. 141 IN A 66.102.9.99
;; Query time: 223 msec
;; SERVER: 208.67.222.222#53(208.67.222.222)
;; WHEN: Mon Dec 14 18:49:21 2009
;; MSG SIZE rcvd: 108
if one of these command does not return an IP address as a result, then the DNS servers are not working. Usually this can be tested with $?==0: if true, the command returned a valid IP address, otherwise there was a problem.
Vim is suitable for a myriad of applications. However, it is in programming where it specially shines. Vim offers facilities that make the programming workflow especially easy and efficient. Some people use newer editors (or IDEs) just because they think Vim lacks some new cool features. That is not the case as I will show you in this issue.
(I will use C source files in the examples, but most of the information in this post is applicable regardless of the language programming you use)
Syntax highlighting
Vim supports syntax highlighting for hundreds of file types. Having a look at /usr/share/vim/vim64/syntax (this is for my linux system, it may vary on your system) reveals 420 different syntax files (one file per file type). Among these, it supports all of the most popular languages (c, c++, basic, yacc, lex, java, html, xml, eiffel, perl…). In addition, Vim also recognizes some other file formats as alsaconf, xf86conf, etc. If Vim has been properly set up after installation, it should detect the file type and color the content accordingly. If that is not the case, you can enable/disable syntax highlighting with :syntax on/off. The picture below depicts three different files (C, bashrc and xorg.conf) with syntax highlighting activated:

Line numbers
Sometimes it is convenient to see line numbers at the left of the window. It helps to quickly locate the line you are interested in. You can do this with :set number or :set nu. To dissable it, use :set nonu[mber]

Parenthesis matching
Vim matches parenthesis and square brackets as you type if the showmatch option is enabled (:set showmatch). If you want to check if your parenthesis are properly balanced, you can place the cursor at one of the parenthesis and type % in command mode. This will move the cursor to the matching parenthesis (if it exists). This works with square and curly brackets too.
Vim counts for you
This is specially cool in my opinion. Ctrl-a and Ctrl-x increments/decrements the number the cursor is placed on. This is especially good because Vim understands different bases. So, typing Ctrl-a in the following scenario:
0x09
0xa
The same works for octal numbers (those that have a leading zero) and, of course, decimal numbers. While this can seem just incidental, it turns out to be really useful if combined with repetition. What is the hexadecimal representation of 1564 (decimal)? Just do the following:
0x0
And now 1564 Ctrl-a ESC (this tells Vim to do Ctrl-a 1564 times). This is what you get:
0x61c
Indentation
Indentation is obviously an important aspect of writing software: it makes the code readable. Vim helps you in this task adding support for indentation. We need to set some global options. You can use these three:
- :set autoindent
- :set smartindent
- :set cindent
The first one sets up a basic indentation. The second one provides an improved one, suitable for C and other programming languages. The third one establishes the specific indentation for C files. I use these three but you should try them and keep only those you feel comfortable with.
Another command to use for indentation is = (equal). It “filters” the text with an external program (if specified) or with the internal C indentation routine. To specify an external filter, you have to set the equalprg variable:
:set equalprog=indent
Note that the definition for filter is “program that accepts text at stantard input, changes it in some way, and sends it to the standard output”. Not all programs match this criteria. Regardless of the rutine used to filter the text, = indents the line where the cursor is placed or the selected text if any.
Tip: G=gg indents the whole file. This is very useful when copy-pasting from another window, remote session, etc, messes the indentation up. In the picture below, the left window shows a code copied from the Internet and the right one, the same text after doing G=gg

You can always indent text blocks freely if the automatic indentation rules do not fit your taste. In order to do this, use the <> commands. Applied twice on a text object they indent that text to the left or to the right.
Commenting out blocks of code
Some times, you need to comment out several lines. There is a quick way to do this and it involves using the free selection command (Ctrl-v). With it you can select portions of text freely. The trick is that after selecting the text, if you type I (capital i), write something at the beginning of the line and press ESCESC, what you just wrote will be inserted at the beginning of all the rest of the selected lines. So if we select the beginning of the line, type I, write // and then ESCESC, those characteres (used as comment markers in C++) will be inserted in each of the selected lines.
Conclusion
This is the first part of “Vim for programmers”. It just shows some of the features that can be used for programming (though most of them are just useful at any time). In the next issue I will cover more of the aspects that make Vim a great editor for programmers.
Vim Sheet (V)
- :syntax on/off Enable/disable syntax highlighting
- :set nu/nonu Enable/disable line numbers
- % matches parenthesis, square brackets and curly braces
- Ctrl-a, Ctrl-x Increment/decrement numbers in different bases.
- =, <<, >> Indent text.