Useful Little Tricks

Kill and signals

Kill really just sends signals to processes; one of those signals happens to be KILL, but there are others, too. Here are some of the more useful ones:

TERM
The default. Ends most processes (somewhat nicely, perhaps?).
KILL
Forcibly takes down a process. Cannot be caught or ignored.
INT
Send ^C to a process
WINGH
Notify a program that its window size has changed (example)
STOP
Forcibly stops a process. It's like ^Z but cannot be ignored. Note that most terminal-based programs don't handle this very gracefully, probably because it bypasses the owning shell/terminal.
CONT
Allows a stopped process to continue, somewhat like fg or bg.
USR1
A user-defined signal. For example, this prompts xdvi to reload the current file.

Bash shell variable/command: !$

Bash will replace '!$' (NOT '$!') with the last token of the previous command, echoing the resulting command before executing it. This can save a lot of repeated typing under some circumstances.

Example: create a directory and then change to it:

$ mkdir ../../foo/bar/baz

$ cd !$
cd ../../foo/bar/baz

$

NOTE: I think there are a bunch of these, but I don't know what they are or what they're called to be able to search for them. Some similar, useful commands are found at http://tldp.org/LDP/abs/html/refcards.html.

Bugs and Annoyances


gcc error messages garbled

You're probably running an xterm without UTF-8 support. Try running

$ xterm -u8

Man page output can also encounter this, usually with line endings that don't wrap properly.

Last encountered Nov 2006


gdb + pthreads = SIG32

This seems to be an issue with gdb not properly garbage collecting dead threads. When anything happens with those 'zombie' threads it catches gdb by surprise, causing SIG32 traps and other strange behaviors.

Solution: tell gdb to keep its nose out of thread signals and let the pthreads library do its job.

(gdb) handle SIG32 nostop noprint pass

WARNING: Every time I have encountered this it turned out to be caused by a bug in my program. This fix will let you keep debugging but may mask problems in your code. Valgrind is your friend!

Last encountered: May 2006

Found in the Linux-Kernel (mailing list) archives


gprof + pthreads gives bogus timing breakdowns

By default gprof does not maintain per-thread timers properly (at all?).

Solution: Unpack and make this this pthread wrapper library, then use it as follows:

$ LD_PRELOAD=gprof-helper.so your-program

Last encountered: Apr 2006

Found at http://sam.zoy.org/writings/programming/gprof.html


Shell command prompt wraps in the middle of a line

Every once in a while a shell doesn't notice that you resized it and its autowrap behavior gets messed up as a result.

Solution: Send the shell a "window changed" signal.

$ kill -WINCH $$

Last encountered: Apr 2006

Emacs (especially for terminal-based editing)

with-args

Sometimes you want to wire up a command to some keystroke, only to discover that it takes arguments. You could write a lambda(), but this is faster and nicer to look at:
(defmacro with-args(&rest args) (list 'lambda nil (list 'interactive nil) args) )
See gdb for example usage

Compiling

Compiling in emacs has two advantages. First, it prompts you to save your sources before attempting to compile (raise your hand if you've ever forgotten that detail and ended up confused). Second, it detects compiler error messages of the form file:line and allows you to jump directly to the offending code. Very nice.
(global-set-key [f12] 'compile)

gdb

Emacs has a wonderful gdb mode that matches up gdb in one buffer with source code in others. You can easily wire up keys to: Especially handy is the ability to easily set run until breakpoints.
(add-hook 'gdb-mode-hook
(lambda()
  ;; begin debugging and break at the first line of main()
  (global-set-key [f5] (with-args gud-call "start"))
  ;; continue executing
  (global-set-key [f6] (with-args gud-cont "%p"))
  (global-set-key [f7] 'gud-finish)
  (global-set-key [f8] 'gud-step)
  (global-set-key [f9] 'gud-next)
  ;; set a temporary breakpoint at the current line and continue executing
  (global-set-key [f10]
		  (lambda ()
		    (interactive nil)
		    (gud-tbreak "%f:%l c")
		    (gud-cont "%p")
		    )
		  )
  ;; make gdb behave more like a normal terminal
  (local-set-key [up] 'comint-previous-input)
  (local-set-key [down] 'comint-next-input)
  )
)

grep-find

This nifty command lets you search for text in a set of files returned by a call to find. In reality, anything that prints out a list of matches starting with file:line will do because it just uses compilation mode.

If that's not powerful/flexible enough, you can also use emacs' dired functionality: http://xahlee.org/emacs/find_replace_inter.html

xt-mouse and big terminal windows

Emacs actually has support for mouse -- including scroll wheel -- in mouse-aware terminals like xterm.
  (require 'xt-mouse)
  (xterm-mouse-mode t)
  (mouse-wheel-mode t)
Unfortunately, xt-mouse assumes that your terminal is only 91 characters wide (or tall), which is often not the case. Clicking out of bounds brings up an annoying menu system instead of moving the point.

The fix? Get ahold of xt-mouse.el and find the xterm-mouse-event function. Very near the beginning it calls read-char to set x and y. Change them to call read-8bit-char (defined below) instead. This hack gives you up to 255 characters, at which point terminals are out of luck.

(defun read-8bit-char ()
  (let ((c (read-char)))
    ; using more than 7 bits?
    (if (= 0 (logand c (- #x100)))
       c ; nope -- normal char
       (+ (logand c #xff) 128) ; yup -- convert to unsigned 8-bit number
    )
  )
)

NOTE: If you don't have root access, or if you only have a pre-compiled xt-mouse.elc installed, you may have to copy xt-mouse.el to a directory (~/.el in my case) and force emacs to find your version first using:

(setq load-path (cons "~/.el" load-path))

Terminals and function keys

All too often terminals are not configured properly for modern (ie newer than 1980) keyboards, and emacs can't properly capture things like arrow keys or combinations of keystrokes.

This file can help a lot, but some things just aren't possible in terminals, especially things like differentiating between ^J and [enter] (the [enter] key was originally a shortcut for ^J, it turns out, just like [tab] was for ^I).

Other pernicious issues include the inability to recognize the [alt] key as a [meta], and inconsistent behavior between terminals on different machines. The latter especially shows up if you use ssh a lot; some host/target combinations just don't play nice for whatever random reason. Sometimes it helps to open an xterm on the target machine. Adding the following entries to ~/.Xdefaults can help with these (and function keys that refuse to behave):

XTerm*eightBitInput:        true
XTerm*metaSendsEscape:      true
XTerm*backarrowKey:         true
XTerm*modifier:             meta