January 16, 2007
Emacs is an incredibly feature rich editor. You can do just about anything you would ever want to do and much more. Unfortunately the power and flexibility of Emacs can be a bit unfriendly and cumbersome at times. I seem to rediscover this fact every 2-3 weeks and I usually customize Emacs in some way to make things easier for me.
My latest discovery is the complicated bookmarking system. Setting a bookmark in Emacs involves moving to the line in the file you want to bookmark, typing C-x r m and then giving the bookmark a unique name. To find the bookmark later, you type C-x r b and then type the unique name you gave the bookmark. This bookmarking system is very flexible but can difficult to work with.
I’ve used Visual Studio in the past and I became quite fond of its simple bookmarking system. You simply type Ctrl-F2 to set a bookmark and F2 to cycle between bookmarks. Shift-F2 cycles bookmarks in reverse. It is such a brain dead system. No need to remember bookmark names. No tiresome keystrokes to type.
Since Emacs is *the* programmable text editor, I was able to extend the existing bookmarking system to emulate the Visual Studio style bookmarks. Now I have a “dumbed down” bookmarking system that is quick and easy to use.
Here’s the code I wrote to make it happen:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Easy bookmarks management
;;
;; Author: Anthony Fairchild
;;
;;;; Keymaping examples
;; (global-set-key [(control f2)] 'af-bookmark-toggle )
;; (global-set-key [f2] 'af-bookmark-cycle-forward )
;; (global-set-key [(shift f2)] 'af-bookmark-cycle-reverse )
;; (global-set-key [(control shift f2)] 'af-bookmark-clear-all )
;; Include common lisp stuff
(require 'cl)
(require 'bookmark)
(defvar af-current-bookmark nil)
(defun af-bookmark-make-name ()
"makes a bookmark name from the buffer name and cursor position"
(concat (buffer-name (current-buffer))
" - " (number-to-string (point))))
(defun af-bookmark-toggle ()
"remove a bookmark if it exists, create one if it doesnt exist"
(interactive)
(let ((bm-name (af-bookmark-make-name)))
(if (bookmark-get-bookmark bm-name)
(progn (bookmark-delete bm-name)
(message "bookmark removed"))
(progn (bookmark-set bm-name)
(setf af-current-bookmark bm-name)
(message "bookmark set")))))
(defun af-bookmark-cycle (i)
"Cycle through bookmarks by i. 'i' should be 1 or -1"
(if bookmark-alist
(progn (unless af-current-bookmark
(setf af-current-bookmark (first (first bookmark-alist))))
(let ((cur-bm (assoc af-current-bookmark bookmark-alist)))
(setf af-current-bookmark
(if cur-bm
(first (nth (mod (+ i (position cur-bm bookmark-alist))
(length bookmark-alist))
bookmark-alist))
(first (first bookmark-alist))))
(bookmark-jump af-current-bookmark)
;; Update the position and name of the bookmark. We
;; only need to do this when the bookmark has changed
;; position, but lets go ahead and do it all the time
;; anyway.
(bookmark-set-position af-current-bookmark (point))
(let ((new-name (af-bookmark-make-name)))
(bookmark-set-name af-current-bookmark new-name)
(setf af-current-bookmark new-name))))
(message "There are no bookmarks set!")))
(defun af-bookmark-cycle-forward ()
"find the next bookmark in the bookmark-alist"
(interactive)
(af-bookmark-cycle 1))
(defun af-bookmark-cycle-reverse ()
"find the next bookmark in the bookmark-alist"
(interactive)
(af-bookmark-cycle -1))
(defun af-bookmark-clear-all()
"clears all bookmarks"
(interactive)
(setf bookmark-alist nil))
8 Comments |
Emacs, Programming |
Permalink
Posted by anthonyf
July 13, 2006
Learning Lisp has been a very enlightening experience for me. But getting the development environment up and running can be quite a chore, especially for a newbie. This can very discouraging if you are used to batteries-included programming languages like Python, Perl, Ruby and even C#. All I can say is be patient, learning Lisp is good for you!
- Install Linux – If you already use Linux then you will likely not have much trouble with the rest of the steps. If you don’t use Linux, why not?? It’s free! Go download Ubuntu Linux or vanilla Debian. Learn to use the package manager. I’m suggesting Linux because it supports all of the open source Common Lisp implementations. Windows has great support for commercial implementations and very poor support (but getting better) for the open source CL’s. I know others use MacOS but I can’t comment since I don’t own a Mac (yet!).
- Learn Emacs – I mean *really* learn it. Learn how to use the help system. Learn Elisp. Learn how to customize it but don’t try to turn Emacs into Notepad or Visual Studio or Vi(m) or whatever your old favorite editor is. Use it the way it was meant to be used. Steal relentlessly and unapologetically from other people’s .emacs config files. In addition to Lisp, Emacs supports just about every other language. Try using it as your primary development environment.
- Use Slime – Slime stands for Superior Lisp Interaction Mode for Emacs. It is simply the best way to develop Lisp code. It has code completion (intellisense), context sensitive help, and includes one of the best debuggers I’ve ever worked with.
- Read some Lisp books – Practical Common Lisp by Peter Seibel is a great starter book. The examples are, as the book title indicates, very practical and additionally easy to follow. Paul Graham’s ANSI Common Lisp is another good beginner’s book which includes a bonus language reference in the back.
- After going though all of the exercises in one or two Lisp books, write a medium-large program using Lisp. Pick something you have done before in another language, or something totally new. The best way to learn a language is to write code!
And that’s it! Easy right? Learning Lisp can tough but it is well worth the effort. I’m so spoiled with it now that I go through severe withdrawals when I have to use Java or C++.
4 Comments |
Emacs, Lisp, Programming |
Permalink
Posted by anthonyf
July 3, 2006
I purchased a new toy yesterday that I’m pretty excited about, a Treo 700p. I’ve been using Palms devices since they were made by 3COM. The main reason I stuck with them for so long is they are very well supported in Linux. Palm also makes a 700w which runs the Windows embedded OS. My friend Keven tells me he read a review that said the 700p has a more intuitive interface over the 700w.
So this Treo is 3 devices in one: a phone, a camera and a palm pilot. Those items purchased separately would probably run about $399, which is what the Treo cost me. Having them all in one device really beats the alternative, which surely involves some kind of fanny pack
Today I installed an open source SSH client on the Treo and was able to connect to my Debian server and run Emacs/Slime on the tiny 320×320 screen. My Treo is now a little Lisp Machine
3 Comments |
Emacs, Gadgets, Lisp |
Permalink
Posted by anthonyf
June 29, 2006
In the “real world” I work at a small software shop and I write C++ code for a Linux embedded system. I say real world because in my fantasy world I write Lisp code for my own company
Anyway, about 100 or so of our C++ header files have the non-standard, Microsoft specific “#pragma once” directive. This directive is short-hand for the more wordy but standard:
#ifndef __SOMEFILE_H__
#define __SOMEFILE_H__
… lots of code…
#endif //__SOMEFILE_H__
In an effort to make the code more portable I decided to replace all of the pragmas with the standard wordy stuff. In most editors I would spend about a 1/2 hour manually searching and replacing text in these files. I would also have to hand type the unique tag for each file. What a pain!
Since I use Emacs this kind of stuff is easy with a quick Elisp helper function:
(defun fix-pragma-once ()
(interactive)
(goto-char 1)
(let ((tag
(upcase (string-replace-match "."
(concat "__" (buffer-name) "__")
"_"))))
(when (search-forward "#pragma once" nil t)
(replace-match (concat "#ifndef " tag) nil t)
(newline)
(insert (concat "#define " tag))
(end-of-buffer)
(insert (concat "#endif //" tag "n")))))
I then use GREP-FIND to find all of the files with “#pragma once” then click them and run the function. The unique tag is generated by getting the buffer name and adding the underscores and finally upcasing it.
Writing the function and then performing the change on all of the files took about 10 minutes. I saved about 2/3 of the time it would have taken me to do it in vis-studio. But blogging about how cool it is just negated the overall time savings. Oh well!
5 Comments |
Emacs, Lisp, Programming |
Permalink
Posted by anthonyf