TabithaTipper

Also known as bluefoo in a lot of places online.

Unix sysadmin for Lancaster University, journeyman coder of Perl and Lisp. Should probably avoid using emacs since she spends a lot of time dinking around with it.

Uses Gnu Emacs built from CVS, and also uses Vim quite heavily during day to day life. Likes the mutt mailer above all others and finds sbcl her preferred Lisp for hacking in.

Questions/comments welcome on any of the below.

Welcome to the wiki! And don’t worry, I keep saying that “we tinker with Emacs because we don’t know what to do with it once we’re done…” – AlexSchroeder

Useful Things To Know Exist

And more fun things

Elisp Snippets

I’ve finally gotten around to yoinking out the useful little bits from my init.el to put up here. You may (require ‘cl) For this to work.

Reading Files

(defun read-file (filename)
  "Takes a filename, reads the data from it and returns it as a string"

  (let* ((real-filename (expand-file-name filename))
         (visited (find-buffer-visiting real-filename))
         (orig-buffer (current-buffer))
         (buf (find-file-noselect real-filename))
         (data (save-excursion
                 (set-buffer buf)
                 (let ((data (buffer-substring-no-properties (point-min) 
                                                             (point-max))))
                   (set-buffer orig-buffer)
                   data))))

    ;; Only kill the buffer if we didn't have a copy when we started
    (if (null visited)
        (kill-buffer buf))

    ;; And return the data.
    data))

Delete to just before match (Vim's dt<char>)

(defun select-region-to-before-match (match &optional dir)
  "Selects from point to the just before the first match of
'match'.  The 'dir' controls direction, if nil or 'forwards then
go forwards, if 'backwards go backwards."
  (let ((start (point))
        (end nil))

    (transient-mark-mode 1)    ;; Transient mark
    (push-mark)                ;; Mark the start, where point is now
    
    (if (or (null dir)
            (equalp 'forwards dir))
        
        ;; Move forwards to the next match then back off
        (progn 
          (search-forward match)
          (backward-char))
      
      ;; Or search backwards and move forwards
      (progn 
        (search-backward match)
        (forward-char)))
    
    ;; Store, then hilight
    (setq end (point))
    (exchange-point-and-mark)

    ;; And return, swap the start/end depending on direction we're going
    (if (or (null dir)
            (equalp 'forwards dir))
        (list start end)
      (list end start))))

(defun select-forwards-to-before-match (match)
  "Selects forwards to just before next match, uses
select-region-to-before-match"
  (interactive "MSelect forwards to just before: ")
  (select-region-to-before-match match 'forwards))

(defun select-backwards-to-before-match (match)
  "Selects backwards to just before next match, uses
select-region-to-before-match"
  (interactive "MSelect backwards to just before: ")
  (select-region-to-before-match match 'backwards))

(defun kill-forwards-to-before-match (match)
  "Selects forwards to just before next match, uses
select-region-to-before-match, then kills that region."
  (interactive "MKill forwards to just before: ")
  (let* ((positions (select-region-to-before-match match 'forwards))
         (start (car positions))
         (end (cadr positions)))
    (kill-region start end)))

(defun kill-backwards-to-before-match (match)
  "Selects backwards to just before next match, uses
select-region-to-before-match, then kills that region."
  (interactive "MKill backwards to just before: ")
  (let* ((positions (select-region-to-before-match match 'backwards))
         (start (car positions))
         (end (cadr positions)))
    (kill-region start end)))

Then just bind kill-backwards-to-before-match and kill-forwards-to-before-match to whatever keys you want.

Kill a line by line number in the buffer

(defun jump-to-line-and-kill (line)
  "Jumps to a specified line and kills it onto the kill ring"
  (interactive "nKill line: ")
  (save-excursion
    (goto-line line)
    (let ((kill-whole-line t))
      (kill-line))))

Looking up functions for (interactive)

(defun foo-ifun-lookup-and-suggest ()
  "A function thats used for (interactive) functions that want to
prompt in the minibuffer for a function name.  Cribbed from describe-function"
  (let* ((fun (function-called-at-point))
         (str (if (null fun)
                  (format "Function: ")
                (format "Function (default %s): " fun)))
         (input (completing-read str obarray 'fboundp 
                                 t nil nil (and fun (symbol-name fun)))))
     
    ;; If we got a value return it
    (list (if (equalp input "")
              fun
            (intern input)))))

This can be used to make writing function lookup style functions easier, such as this method of doing a CLHS lookup using Slime

(defun clhs-lookup (arg)
  "Lookup a symbol from the CLHS using #'common-lisp-hyperspec"
  (interactive (foo-ifun-lookup-and-suggest))
  (common-lisp-hyperspec arg))

Remove totally blank lines at the end of files

This is useful when editing mails from mutt within emacs, somehow a couple of blanks get appended in my setup.

(defun goto-start-of-last-line ()
  "Moves the point to the start of the line line in the buffer"
  (goto-line (+ (count-lines (point-min) (point-max)) 1))
  (beginning-of-line))

(defun last-line-blank ()
  "Returns T if the last line in the buffer is blank, return nil otherwise"
  (save-excursion
    (goto-start-of-last-line)
    (= (point) (point-max))))

(defun delete-trailing-blank-lines ()
  "Deletes all blank lines at the end of the file.  These must be
truely blank and contain no whitespace."
  (interactive)
  (save-excursion
    (while (last-line-blank)
      (progn
        (goto-start-of-last-line)
        (delete-region (- (point) 1) (point-max))))))

You can then switch this on to automatically happen for mails

    (add-hook 'post-mode-hook 'delete-trailing-blank-lines)

Interaction between physical and longlines

(defun setup-physical-line-mode ()
  "Sets up physical line mode and rebinds keys to give moving by logical lines 
and physical lines.

Home/End move by physical (screen) whereas C-a/C-e move by
logical (file) lines"
  (interactive)

  (require 'physical-line)

  (physical-line-mode-on)

  ;; Home/End for moving on the screen-lines, C-a/C-e for moving
  ;; across logical file lines.
  (local-set-key [(home)] 'physical-line-beginning-of-line)
  (local-set-key [(end)] 'physical-line-end-of-line)
  (local-set-key (kbd "C-a") 'physical-line-beginning-of-logical-line)
  (local-set-key (kbd "C-e") 'physical-line-end-of-logical-line))

(defun setup-longlines-mode ()
  "Sets up longlines mode and binds some keystrokes,
specifically tries to fix C-a/C-e for moving by logical (file)
lines, leaving Home/End to work on the physical (screen) line.

FIXME: Still want long-lines mode to show wrapping arrows in the
trough."
  (interactive)

  (require 'longlines)

  ;; Generally emacs23 ships with a version of longlines that uses
  ;; escape-glyph, older versions used longlines-visible-face
  (setf longlines-show-effect 
        (if (>= emacs-major-version 23)
            (propertize "$\n" 'face 'escape-glyph)
          (propertize "$\n" 'face 'longlines-visible-face)))

  ;; (longlines-show-hard-newlines) ;; Annoying for copying/pasting

  ;; Make sure it deals with resizes.
  (setq longlines-wrap-follows-window-size t)

  (longlines-mode 1)

  ;; (longlines-show-hard-newlines) ;; Gets in the way of copypasta


  ;; Bind the keys with anonymous functions.  Note that only
  ;; going backwards do we have to check to see if we're at the
  ;; start of the buffer, going endwards isn't an issue, unless
  ;; your the kind of muppet who lets your editor insert random
  ;; newlines at the end of things.
  (local-set-key (kbd "C-a") #'(lambda ()
                                 (interactive)
                                 (progn (backward-paragraph)
                                        (if (not (= (point) (point-min)))
                                            (forward-char)))))
  (local-set-key (kbd "C-e") #'(lambda ()
                                 (interactive)
                                 (progn (forward-paragraph)
                                        (backward-char)))))

(defun ll-text-mode ()
  "text-mode with longlines minor mode enabled, only for
      specific text files"
  (interactive)
  (text-mode)

  ;; In this order so the longlines keybindings overwrite properly
  (setup-physical-line-mode)

  ;; 2008-12-16, the new word-wrap variable is in this page
  ;; http://www.emacswiki.org/emacs/LineWrap Works.
  ;;
  ;; Works more reliably than longlines mode, but is only
  ;; available in GNU Emacs CVS after about September.
  ;; 
  ;; word-wrap also keeps the home/end (screen), C-a/C-e (logical)
  (if (boundp 'word-wrap)
      (setq word-wrap t)
    (setup-longlines-mode))

  (flyspell-mode 1))

;; All text modes is a bit wide, that hits latex and other
;; stuff, be cautious and only use it for .txt and .text files.
;;
;; Although perhaps its a good plan...
;;(add-hook 'text-mode-hook 'longlines-mode)

(add-to-list 'auto-mode-alist '("\\.txt$" . ll-text-mode))
(add-to-list 'auto-mode-alist '("\\.text$" . ll-text-mode))

;; Setup physical line mode for latex
(add-hook 'latex-mode-hook 'setup-physical-line-mode)

Editing Mail inside Emacs

(require 'post) ;; For writing mail-like files

;; Change message for post-mode
(defadvice server-process-filter (after post-mode-message first activate)
  "If the buffer is in post mode, overwrite the server-edit
	   message with a post-save-current-buffer-and-exit message."
  (if (eq major-mode 'post-mode)
      (message
       (substitute-command-keys "Type \\[describe-mode] for help composing; \\[post-save-current-buffer-and-exit] when done."))))

;; Should jump to body for all posting.
(add-hook 'server-switch-hook
          (lambda ()
            (cond ((string-match "Post" mode-name)
                   (post-goto-body)))))

;; Remove blank lines, some interaction between mutt and emacs
(add-hook 'post-mode-hook 'delete-trailing-blank-lines)

HTTP proxying

(setq *long-proxy* "http://proxy.example.com:8080"
      *short-proxy* "proxy.example.com:8080")

(setenv "http_proxy" *long-proxy*)
(setenv "ftp_proxy" *long-proxy*)
(setq url-proxy-services
      '(("http"     . *short-proxy*)
	("ftp"      . *short-proxy*)
	("no_proxy" . "^.*example.com")))

Dictionary Server

See http://www.myrkr.in-berlin.de/dictionary.html for more.

(setq dictionary-server "localhost")

(require 'dictionary)
(eval-after-load "dictionary"
  '(progn
    (load-file (expand-file-name "~/.elisp/dictionary/dictionary-init.el"))
    
    (global-dictionary-tooltip-mode 1)
    
    (global-set-key "\C-cs" 'dictionary-search)
    (global-set-key "\C-cm" 'dictionary-match-words)))

CategoryHomepage