shell

Vim for programmers (III)

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.

shell

RPM: Listing dependencies of an rpm file

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)

shell

Vim for programmers (II)

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
n0str0m0 | # | (0)

shell

Mounting and unmounting a disk image (dmg) in OS X

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.

shell

Are your DNS Servers failing?

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.

shell

Vim for programmers (I)

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:

vim_syntax_example

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]

vim_lines_numbers

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

vim_indentation

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.

news

SysAdvent Calendar 2009

SysAdvent is a project started by Jordan Sissel last year. It consists of sysadmin related posts. A post a day from 1st to 25th Dec. Jordan takes that idea from the Perl Advent Calendar.

This year there are some bloggers helping Jordan on this task.

I recommend subscribing to it, their posts are quite useful.

shell

screen: working with the scrollback buffer

screen is a full-screen window manager that multiplexes a physical terminal between several processes, typically interactive shells. That is, multiple console applications can be run from the same terminal, each one with its own window. But we have already talked about the screen command before. In this post we are going to focus on the scrollback buffer feature.

There is a scrollback history buffer for each virtual terminal, allowing to browse, or even to search, through the history of your windows. There is a copy-and-paste mechanism as well that allows moving text regions between windows.

By default, the buffer has only the last 100 lines of text. It can be modified running screen with the -h option:

$ screen -h 2000

It can be set in the .screenrc file too, by adding the following line:

defscrollback 5000

Finally, if you want to change the number of lines of scrollback for a single window, type C-a (Ctrl-A) to go to the screen command line and type:

scrollback num

where num is the number of scrollback lines.

To check the number of scrollback lines in your window type C-a i to display that window’s information. A line with information will be shown:

(11,1)/(80,49)+2000 +flow UTF-8 0(bash)

In this case, my scrollback is 2000 lines.

To enter scrollback/copy mode type C-a [
A status line will indicate that you have entered copy mode. Navigating in scrollback mode will be pretty familiar to vi users:

Movement keys:

  • h, j, k, l move the cursor line by line or column by column.
  • 0, ^ and $ move to the leftmost column, to the first or last non-whitespace character on the line.
  • H, M and L move the cursor to the leftmost column of the top, center or bottom line of the window.
  • + and - positions one line up and down.
  • G moves to the specified absolute line (default: end of buffer).
  • | moves to the specified absolute column.
  • w, b, e move the cursor word by word.
  • B, E move the cursor WORD by WORD (as in vi).
  • C-u and C-d scroll the display up/down by the specified amount of lines while preserving the cursor position. (Default: half screen-full).
  • C-b and C-f scroll the display up/down a full screen.
  • g moves to the beginning of the buffer.
  • % jumps to the specified percentage of the buffer.

Screen allows you to search the scrollback buffer using the following commands.

Searching:

  • / Vi-like search forward
  • ? Vi-like search backward
  • C-a s Emacs style incremental search forward
  • C-r Emacs style reverse i-search

In scrollback mode (or copy mode, it is the same) you can copy and paste text. The copy range is specified by setting two marks. The text between these marks will be highlighted.

Marking:

  • space to set the first or second mark respectively.
  • Y and y used to mark one whole line or to mark from start of line.
  • W marks exactly one word.

Once the text is marked, move to the window where the text is going to be copied and type C-a ]

To exit scrollback mode, hit the esc (escape) button.

For more info, man screen as always :)

shell

Changing file extension

I usually change the annoying JPG extension to jpg (I do not like uppercase file names or extensions). For this I use a function I found in shell-fu:

rename_ext() {
   local filename
   for filename in *."$1"; do
     mv "$filename" "${filename%.*}"."$2"
   done
}

I copied it into my .bashrc file, so that I use it as follows:

$ rename_ext JPG jpg