Articles

Dot-Emacs Tips

Free, Portable and Extensible

Emacs is free (you can do what you want with the source code), portable (it works on any machine) and extensible (you can customise everything about Emacs to your own taste and style of working). Extensibility is the most important part of Emacs and comes about because it is written in a proper programming language — Lisp in the case of GNU Emacs.

Emacs Initialisation File

I don't claim that anything in my dot-emacs file is original, efficient or good Lisp style. It works for me, but please be aware your experience may be different. The extracts given below are from my dot-emacs file. They come with brief comments, written in note form. It goes without saying that where the terms "user", "username", etc. occur, they should be replaced by your user-name.

Byte-Compile

If your dot-emacs file is large (say, more than a thousand lines) then it is more efficient (and faster) to byte-compile the file to ".emacs.elc", which of course is loaded in preference to the un-compiled initialisation file.

;;-----------------------------------------------------------------
;;
;; Byte-compile ".emacs" everytime it is saved.
;;
;;-----------------------------------------------------------------
(defun byte-compile-user-init-file ()
(let ((byte-compile-warnings '(unresolved)))
;;
;; In case compilation fails, don't leave old .elc around:
;; NB Does not always work. Sometimes hand-delete is required.
(when (file-exists-p (concat user-init-file ".elc"))
(delete-file (concat user-init-file ".elc")))
(byte-compile-file user-init-file)
;; Send out message:
(message "%s compiled" user-init-file)
))

(defun my-emacs-lisp-mode-hook ()
(when (equal buffer-file-name user-init-file)
(add-hook 'after-save-hook 'byte-compile-user-init-file t t)))

;; (add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)
(add-hook 'emacs-lisp-mode-hook 'my-emacs-lisp-mode-hook)
;;

Custom Set Variables

I prefer to have the custom-set-variables and faces at the beginning of my dot-emacs file. Then I can over-ride the settings later to a different choice.

Use Messages

I find out-putting messages during the loading of my dot-emacs useful for debugging. So I use something like this:

(message "Message: Begin whatever ...")
... "whatever" ....
(message "Message: End whatever ...")

at the beginning and end of various sections of the dot-emacs. Usually, things happen too quickly for the messages to be easily seen as they are loaded, but they can be read at leisure by entering "C-x b" and selecting the *Messages* buffer.

Fonts

When I first started using emacs I had problems selecting a suitable font. I list here the ones I have found over time that work for me.

;; Enable UTF-8 by default
(setq locale-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
;;
;;
;;;
;;; Select default font from:
;;;
;; "Adobe Courier 18" - large, a full-window font - best for a laptop?
;(set-default-font "-adobe-courier-medium-r-normal--18-180-75-75-m-110-iso8859-1")
;;
;; "Adobe Courier 14" - smaller than above, very nice font.
;;(set-default-font "-adobe-courier-medium-r-normal--14-140-75-75-m-90-iso8859-1")

;; "xos4 Terminus" - nice window font
;;(set-default-font "-xos4-terminus-bold-r-normal--16-140-*-72-c-80-iso8859-1")

;; "terminus-20" - very large full-window font.
;(set-default-font "terminus-20")

;; "Terminus-12" - small window terminal font.
;;(set-default-font "Terminus-12")

;; "terminus-14" - ok window terminal font.
;;(set-default-font "terminus-14")

;; "9X15" - nice no-frills terminal font.
;;(set-default-font "9x15")

Time-Stamps for Files

It is very useful to insert a time-stamp automatically into a file when saving. The stamp can give not just the date and time, but such things as the name of the user and host-name of the machine.

;;;
;;; By default, to add a timestamp in a file,  add the line 
;;; "Time-stamp: <>"
;;; (without the quotes) somewhere in the first 10 lines of the file.
;;; If you use LaTeX then insert:
;;; "\noindent Time-stamp: <>"
;;; (without the quotes) for a printout of the time-stamp.
;;;
(setq 
time-stamp-active t          ;;; Eenable time-stamps.
time-stamp-line-limit 10     ;;; Check first 10 lines for Time-stamp.
                             ;;; Change to another number if you wish.
;;;
;;; Format - "date, time, username"
;time-stamp-format "%04y-%02m-%02d %02H:%02M:%02S (%u)")
;;; Format - "date, time" 
;time-stamp-format "%04y-%02m-%02d %02H:%02M:%02S")
;;; Format - "date, time, (username@host)"
time-stamp-format "%04y-%02m-%02d %02H:%02M:%02S (%u@%s)")
;;; 
;;; Update time-stamp when saving file.
(add-hook 'write-file-hooks 'time-stamp)

w3m

I tend to use w3m in preference to firefox when I only want to read text. It is much faster and uncluttered. All my w3m settings are contained in a separate initialisation file ".emacs-w3m.el" kept in my home directory. I have the following lines in my dot-emacs file:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; w3m mode
;;; 
;;; version: w3m-1.4.4
;;;
;;; This is located towards the end of "~/.emacs" in oder to avoid  
;;; any conflicts with "~/.emacs-w3m.el".
;;; w3m is called by M-x w3m RET.
(require 'w3m-load)
;;
;;; Add the next two lines
(require 'w3m-e21)
(provide 'w3m-e23)
;;; to allow for fact that w3m-1.4 does not support emacs-23.
;;;
;;; All w3m-related code is in "~/.emacs-w3m.el".
;;; w3m knows about ".emacs-w3m.el" so path does not need to
;;; be set explicitly.

My ".emacs-w3m.el" file looks like this:

;; w3m-init-file
;;
;; ".emacs-w3m.el"
;;
;;;;;;;;;;;;;;;;;;;
;;
;; When emacs-w3m starts, it will read the w3m-init-file. The default value
;; is `~/.emacs-w3m'. You probably don't need to change this. This is a normal
;; Emacs Lisp file and can be used to avoid cluttering your `~/.emacs' and
;; `site-init' files with emacs-w3m stuff. Emacs-w3m will also check for files
;; with the same names as this, but with `.elc' and `.el' extensions (in other
;; words, `~/.emacs-w3m.elc', `~/.emacs-w3m.el' and `~/.emacs-w3m', in this
;; order).
;;
;; Please note that some variables from external modules could be undefined 
;; at the time the `~/.emacs-w3m' file is loaded, thus making them impossible 
;; to modify (of course if you don't care about the default value, you can 
;; override them completely in your `~/.emacs-w3m') file. 
;; The w3m-search-engine-alist variable is a typical example.

;; w3m now default browser
(setq browse-url-browser-function 'w3m-browse-url)
(autoload 'w3m-browse-url "w3m" "Ask a WWW browser to show a URL." t)

;; Home Page - Select one:
;(setq w3m-home-page "http://choose.web-site")
(setq w3m-home-page "file:///path/to/html/file")

;; set cookies
(load "w3m-cookie")
(setq w3m-use-cookies t
      w3m-cookie-file "/home/user/.w3m/cookie"
      w3m-cookie-accept-bad-cookies t
      w3m-cookie-accept-domains '("domain" 
                                  "another.domain"
                                  "yet.another.domain")
);; End bracket.

;; Open a new tab by typing RET on a url string.
(setq w3m-make-new-session t)

;; optional keyboard short-cut
 (global-set-key "\C-xm" 'browse-url-at-point)

;;; C-c C-t creates new tab with line below:
(setq w3m-use-tab t)

;;;
;;; Removing trailing whitespace in w3m buffer
;;;
(add-hook 'w3m-display-hook
          (lambda (url)
            (let ((buffer-read-only nil))
              (delete-trailing-whitespace))))
;;;
;;;

;;;
;;;
;;; Switch-off doc-view!!!!!!!!!
;;;
;;;
;; By default, emacs-w3m uses a Lisp function specified
;; by the `w3m-local-find-file-function' variable for those files.
;; To let emacs-w3m use external commands even for browsing local
;; files, simply set this to nil as follows:
(setq w3m-local-find-file-function nil)
;; By the way, "gv" and "xpdf" should be set as the viewers for ps
;; files and pdf files in the `w3m-content-type-alist' variable by
;; default, if you have those commands installed in PATH (of which
;; the value is inherited into the `exec-path' variable in Emacs).
;; So, you don't seem to need to customize it.


;;;
;;; Customize searches
;;;
;;; Find the entry point of the search engine you want to add, 
;;; for example:
;;;   
;;;    http://my.searchengine.com/?query=foobar
;;;   
;;;    where foobar is the term you want to search for.
;;;   
;;; Then add info to your ‘~/.emacs-w3m’ file:
;;;   
;;;      (eval-after-load "w3m-search"                            
;;;        '(add-to-list 'w3m-search-engine-alist                 
;;;                      '("My engine"                            
;;;                        "http://my.searchengine.com/?query=%s" 
;;;                        nil)))   


;;;
;;; Copying URL at point
;;; Key bind to Alt-W 
;;;
(defun w3m-copy-url-at-point ()
  (interactive)
  (let ((url (w3m-anchor)))
    (if (w3m-url-valid url)
        (kill-new (w3m-anchor))
      (message "No URL at point!"))))
;;
(add-hook 'w3m-mode-hook
          (lambda ()
            (local-set-key "\M-W" 'w3m-copy-url-at-point)))
;;
;;

;;;
;;; Download with wget
;;;
(defun w3m-download-with-wget (loc)
  (interactive "DSave to: ")
  (let ((url (or (w3m-anchor) (w3m-image))))
    (if url
        (let ((proc (start-process "wget" (format "*wget %s*" url)
                                   "wget" "--passive-ftp" "-nv"
                                   "-P" (expand-file-name loc) url)))
          (with-current-buffer (process-buffer proc)
            (erase-buffer))
          (set-process-sentinel proc (lambda (proc str)
                                       (message "wget download done"))))
      (message "Nothing to get"))))
;;

My ".emacs-w3m.el" file is too small to make bye-compiling worthwhile.

Encryption using gpg

I use gpg (symmetric) encryption for my diary and bbdb files, as well as for RMAIL (see next Section).

;;; Diary
;;;-------
;;; Set as Encrypted diary file, and set path.
;;; You will be prompted for password.
;;; Obviously do not encrypt if you find password
;;; prompting annoying, especially if you are using
;;; diary as part of org-mode agenda.
(setq diary-file "~/path/to/diary.gpg")
;;;
;;;

;;; bbdb
;;;-------
;;; Set bbdb file as encrypted, and set path.
;;; You will be prompted for password.
(setq bbdb-file "~/path/to/bbdb.gpg")
;;;
;;;

RMAIL and Personal Data

I have all my personal settings, like email addresses, etc., in an encrypted file "personal_info.gpg" along the lines of:

;;;
;;; Personal data
;;; File Name: personal_info.gpg"
;;; Encrypted by "symmetric" gpg.

;; 
;; Necessary to avoid errors in the "From" field of RMAIL.
;;
;; Setup my full name
(setq user-full-name "Your Name Here")
;; Setup my email address
(setq user-mail-address "your_email@address.here")

;;;;;;;;;
;;;
;;; This is the set-up I use for gmail. Other smtp mailers should
;;; work in a similar fashion.
;;; To receive mail, I use fetchmail with the following ~/.fetchmailrc
;;;
;;; ------- Begin /home/user/.fetchmailrc ------
;;;
;;; # Configuration created .....
;;; set postmaster "user"
;;; set bouncemail
;;; set no spambounce
;;; set properties ""
;;; poll pop.gmail.com with proto POP3 and options no dns
;;; user 'your_gmail_username@gmail.com' there is 'user' here options ssl
;;;
;;; ------- End /home/user/.fetchmailrc --------
;;;
;;; gmail
;;;
;;; You will be prompted for your gmail password.
;;;
(setq message-send-mail-function 'smtpmail-send-it
smtpmail-starttls-credentials '(("smtp.gmail.com" 587 nil nil))
smtpmail-auth-credentials '(
    ("smtp.gmail.com" 587 "your_gmail_username@gmail.com" nil))
      smtpmail-default-smtp-server "smtp.gmail.com"
      smtpmail-smtp-server "smtp.gmail.com"
      smtpmail-smtp-service 587
;;; Do not set next line unless server complains
;;;    smtpmail-local-domain "gmail.com"
) ;; End bracket.
;;;
;;;

The above file is activated through "personal.el", which looks like this:

;;; personal.el --- Access to personal information
;;;

;; Author: Colin Baxter
;; Keywords: Personal information

;; This file is NOT part of GNU Emacs.

;;; Commentary:
;; None


;; Code
(let ((personal-settings "~/path/to/personal_info.gpg"))
(when (file-exists-p personal-settings)
(load personal-settings)))


(provide 'personal)

;;; End "personal.el".

The path to "personal.el" must be found by emacs so put

(setq load-path  (cons (expand-file-name "/path/to/personal.el") load-path))

in the dot-emacs file. Then to load "personal.el" I use

M-x load-libray RET
personal RET
password RET

I do it this way because If "personal.el" were to be called directly from dot-emacs then the emacs screen would sometimes hang. I have not found a work-round for this.

Org-Mode

My org-mode settings are extensive, but they generally follow those available here.