credmp Ramblings of a code junkie Sun, 18 Feb 2007 13:11:28 +0000 en Optimizing Emacs usage Sun, 18 Feb 2007 13:11:28 +0000 core emacs steve yegge tips keyboard mappings After reading Steve Yegge’s blog post ‘Effective Emacs’ I tried several of his tips. I already have my Capslock changed to the CTRL key (In Mac OS X this is done by going to system preferences, Keyboard and Mouse, Keyboard, press the ‘Modifier keys…’ button and change the mapping). But I have always used the Command key (the one with the apple logo) to invoke ‘M-x’ / execute-extended-command. In some terminals that just doesn’t fly. I added a mapping to bind it to ‘C-x C-m’ which is surprisingly easy to utilize! I also started using the ‘C-w’ mapping to replace backspacing a complete word and remapping kill-region to the alternative Steve suggests, most excellent!

The adjusted mappings are these:

(global-set-key "\C-x\C-m" 'execute-extended-command)
(global-set-key "\C-w" 'backward-kill-word)
(global-set-key "\C-x\C-k" 'kill-region)

Like all changes, you should not do everything at once, although Steve has a great deal of tips on streamlining your Emacs usage, just changing too much at once will slow you down. Change 1 or 2 things, get used to it, then change something else that annoys you.

Speech recognition programming Sun, 18 Feb 2007 12:19:55 +0000 core speech recognition windows vista programming perl Found this video of some guy trying to write some perl code with the windows vista speech recognition feature, needless to say, vista falls short of being usefull in this context…

Don’t think speech recognition will become helpfull for programming for a long time…

Taking care of tags Sun, 18 Feb 2007 07:40:24 +0000 core autometa boakes plugin wordpress Today I found the AutoMeta plugin for wordpress. This plugin does a full text scan of your post and creates tags based on word scores. It then generates the META as well as the technorati tags…. which is quite sweet, saves a lot of hand writing them!

OpenID going mainstream? Sat, 17 Feb 2007 14:59:13 +0000 core
Warning: Invalid argument supplied for foreach() in /home/www/arjen/ on line 300 OpenID has been getting quite some attention lately, the most massive news I have heard so far however is that AOL has created an openid server with all AIM/AOL accounts. This means that suddenly 63 million accounts have an usable openid url. OpenID is great for online identity management, being able to leave blog or forum posts without having to deal with irritating registration procedures…

It’s not really a secret that AOL has been experimenting with OpenID. As I’ve said, I think that user-centric, interoperable identity is hugely important to enable the social experiences we’re trying to provide.  This is a work in progress, but things are coming along thanks to our authentication team’s diligent effort.  Here’s where we are today:

  • Every AOL/AIM user now has at least one OpenID URI,<sn>.
  • This experimental OpenID 1.1 Provider service is available now and we are conducting compatibility tests.
  • We’re working with OpenID relying parties to resolve compatibility issues.
  • Our blogging platform has enabled basic OpenID 1.1 in beta, so every beta blog URI is also a basic OpenID identifier.  (No Yadis yet.)
  • We don’t yet accept OpenID identities within our products as a relying party, but we’re actively working on it.  That roll-out is likely to be gradual.
  • We are tracking the OpenID 2.0 standardization effort and plan to support it after it becomes final.

Hopefully more companies/products will pick up on this and start offering openid services, it would be a means to remove us from the shackles of ever lasting login procedures and registration annoyances…

Words of advice Sat, 17 Feb 2007 14:27:51 +0000 core
Warning: Invalid argument supplied for foreach() in /home/www/arjen/ on line 300 Anyone programming or thinking about programming for a company should read this story…. the soundest advice you will get :)

C++ lexicographical_compare and locales Tue, 16 Jan 2007 11:24:57 +0000 core
Warning: Invalid argument supplied for foreach() in /home/www/arjen/ on line 300 While doing a bit of research into sorting strings in C++ (a seemingly easy task) I ran into various issues. For one, locales. If you have a string that uses ‘\334′ or ü as it is in human readable form, it is not taken into account by the normal case insensitive sorting algorithms.

I found a paper, “How to do case-insensitive string comparison” written by “Matt Austern“. He provides a good explanation and a sound solution to the problem. However, I prefer to utilize the C++ data encapsulation paradigms and have re-written the code to be more readable / usable (my opinion anyways;). All classes have moved to their own header files, private members are actually private and you can now use the code in various places in your code since the header files are guarded.

The code is seperated over 4 files:


#ifndef LT_CHAR_H
#define LT_CHAR_H

class lt_char {
    lt_char(const char *table);

    bool operator()(char x, char y) const;
    const char *char_table;

#endif // LT_CHAR_H


#include "lt_char.hpp"

lt_char::lt_char(const char *table) : char_table(table) {

bool lt_char::operator()(char x, char y) const {
    return char_table[x - CHAR_MIN] < char_table[y - CHAR_MIN];


#ifndef LT_STRING_H
#define LT_STRING_H


class lt_string : public std::binary_function {
    lt_string(const std::locale &locale = std::locale::classic());

    bool operator()(const std::string &x, const std::string &y) const;
    char char_table[CHAR_MAX - CHAR_MIN + 1];

#endif // LT_STRING_H


#include "lt_string.hpp"
#include "lt_char.hpp"

lt_string::lt_string(const std::locale &locale) {
    const std::ctype &ctype_char = std::use_facet< std::ctype >(locale);

    for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) {
        char_table[i - CHAR_MIN] = (char) i;

    ctype_char.toupper(char_table, char_table + (CHAR_MAX - CHAR_MIN + 1));

bool lt_string::operator()(const std::string &x, const std::string &y) const {
    return std::lexicographical_compare(x.begin(), x.end(),
                                        y.begin(), y.end(),
Network based installation of Linux distros Thu, 21 Dec 2006 10:09:10 +0000 core
Warning: Invalid argument supplied for foreach() in /home/www/arjen/ on line 300 How to forge has a great article up on how to install linux over a network connection using you own Preboot eXecution Environment installation server. This will allow you to play around with various distributions without the need of burning CDs / DVDs of each distribution.

The Article

Mapping software Thu, 21 Dec 2006 09:40:48 +0000 core
Warning: Invalid argument supplied for foreach() in /home/www/arjen/ on line 300 Recently I did some research in mapping software. So far I found 2 reasonable packages that can be used in an automated fashion:

While GMT is probably the most extensive one, GRASS (for now) seems to be the most flexible from an automated standpoint.

The idea is to make a C++ application to spit out some maps with statistics on several things… the initial test will of course be earthquake maps, which seem to be the ‘hello world’ of mapping :)

More Emacs goodness Thu, 30 Nov 2006 19:24:39 +0000 core
Warning: Invalid argument supplied for foreach() in /home/www/arjen/ on line 300 Found a couple of interesting blogposts about Emacs:

Ruby On Rails and Emacs Tue, 28 Nov 2006 13:54:03 +0000 core
Warning: Invalid argument supplied for foreach() in /home/www/arjen/ on line 300 Ruby on Rails is quite a hot topic nowadays and with all the major RoR people using TextMate as their editor there seems little interest in using the one true editor for these tasks.

I started playing with RoR and of course I use Emacs for this. The following describes setting up Emacs for RoR development.

Setting up Emacs

First, you need to get the emacs-rails package for easy RoR development and put it in an directory where you keep your other Emacs packages, I use *.elisp*:

.elisp$ svn checkout svn:// emacs-rails

Besides the emacs-rails there are some other helper files you need:

.elisp$ wget
.elisp$ mv find-recursive.txt find-recursive.el

The ruby-mode files are available in the ruby distribution in the *misc* directory.

Ok, so now we have all the components, lets tell Emacs what it needs to know (note I copied the ruby-mode files to my .elisp directory and my .elisp directory is already on the load-path):

(setq load-path (cons "~/.elsip/ruby-mode" load-path))
(autoload 'ruby-mode "ruby-mode" "Load ruby-mode")
(add-hook 'ruby-mode-hook 'turn-on-font-lock)

(setq load-path (cons "~/.elisp/emacs-rails" load-path))
(defun try-complete-abbrev (old)
  (if (expand-abbrev) t nil))

(setq hippie-expand-try-functions-list

(require 'rails)

;; associate ruby-mode with .rb files
(add-to-list 'auto-mode-alist '("\.rb$" . ruby-mode))

;; make #! scripts executable after saving them
(add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)

Cool, so now we have ruby mode. Lets setup rhtml file editing (if you do not have the mmm-mode package, you should install it).

(require 'mmm-mode)
(require 'mmm-mode)
(require 'mmm-auto)
(setq mmm-global-mode 'maybe)
(setq mmm-submode-decoration-level 2)
(set-face-background 'mmm-output-submode-face  "LightGrey")
(set-face-background 'mmm-code-submode-face    "white")
(set-face-background 'mmm-comment-submode-face "lightgrey")
    :submode ruby-mode
    :match-face (("<%#" . mmm-comment-submode-face)
                 ("<%=" . mmm-output-submode-face)
                 ("<%"  . mmm-code-submode-face))
    :front "<%[#=]?"
    :back "-?%>”
    :insert ((?% erb-code       nil @ “<%"  @ " " _ " " @ "%>” @)
             (?# erb-comment    nil @ “<%#" @ " " _ " " @ "%>” @)
             (?= erb-expression nil @ “<%=" @ " " _ " " @ "%>” @))
(add-hook ‘html-mode-hook
          (lambda ()
            (setq mmm-classes ‘(erb-code))
(add-to-list ‘auto-mode-alist ‘(”\.rhtml$” . html-mode))

;; shortcut to reparse the buffer
(global-set-key [f8] ‘mmm-parse-buffer)

Now when you open a *.rhtml* file you will have access to the full ruby-mode in the appropiate areas.

Alright, so what can you do? Basically everything you would need to do for RoR, only then from Emacs. From creating a project, to running the webrick server to generating models, controllers, scaffold etc. It also has some handy functions to navigate between the different directories.

From a code expansion viewpoint there are many predefined snippets, which you can of course extend all you like. All the standard keybindings and abbreviations are listed here.

An example of abbreviations at work:

  def hello
    flash[press tab]

Expands to, with the cursor on the highlighted ‘:notice’, press tab to go to the second field (text).

  def hello
    flash[:notice] = “Text here…  end

Type ‘Invalid product’ in the text field and press tab again

  def hello
    flash[:notice] = “Invalid product  end

The statement is now complete

  def hello
    flash[:notice] = “Invalid product”


  ((kbd "C-c g m") 'rails-nav:goto-models)
  ((kbd "C-c g c") 'rails-nav:goto-controllers)
  ((kbd "C-c g h") 'rails-nav:goto-helpers)
  ((kbd "C-c g l") 'rails-nav:goto-layouts)
  ((kbd "C-c g s") 'rails-nav:goto-stylesheets)
  ((kbd "C-c g j") 'rails-nav:goto-javascripts)
  ((kbd "C-c g g") 'rails-nav:goto-migrate)

  ;; Switch
  ((kbd "C-c <up>") 'rails-lib:run-primary-switch)
  ((kbd "C-c <down>") 'rails-lib:run-secondary-switch)

  ;; Scripts & SQL
  ((kbd "C-c s g c") 'rails-generate-controller)
  ((kbd "C-c s g m") 'rails-generate-model)
  ((kbd "C-c s g s") 'rails-generate-scaffold)
  ((kbd "C-c s g g") 'rails-generate-migration)
  ((kbd "C-c s d c") 'rails-destroy-controller)
  ((kbd "C-c s d m") 'rails-destroy-model)
  ((kbd "C-c s d s") 'rails-destroy-scaffold)
  ((kbd "C-c s c")   'rails-run-console)
  ((kbd "C-c s b")   'rails-run-breakpointer)
  ((kbd "C-c s s")   'rails-run-sql)
  ((kbd "C-c s r")   'rails-rake)
  ((kbd "C-c s w")   'rails-webrick:start)

  ;; Rails finds
  ((kbd "C-c f m") 'rails-find-models)
  ((kbd "C-c f c") 'rails-find-controller)
  ((kbd "C-c f h") 'rails-find-helpers)
  ((kbd "C-c f l") 'rails-find-layout)
  ((kbd "C-c f s") 'rails-find-stylesheets)
  ((kbd "C-c f j") 'rails-find-javascripts)
  ((kbd "C-c f g") 'rails-find-migrate)

  ((kbd "C-c f v") 'rails-find-view)
  ((kbd "C-c f d") 'rails-find-db)
  ((kbd "C-c f p") 'rails-find-public)
  ((kbd "C-c f f") 'rails-find-fixtures)
  ((kbd "C-c f o") 'rails-find-config)

  ;; Navigation
  ((kbd "<C-return>") 'rails-goto-file-on-current-line)
  ((kbd "<M-S-down>") 'rails-goto-file-from-file-with-menu)
  ((kbd "<M-S-up>")   'rails-goto-file-from-file)
  ((kbd "C-c l") 'rails-open-log)

  ;; Tags
  ((kbd "C-c C-t") 'rails-create-tags)

  ;; Browser
  ((kbd "C-c <f5>") 'rails-webrick:auto-open-browser)
  ;;; Doc
  ([f1]  'rails-search-doc)
  ((kbd "<C-f1>")  'rails-browse-api-at-point)
  ((kbd "C-c <f1>")  'rails-browse-api)

  ([f9]  'rails-svn-status-into-root))

All actions are also available through M-x rails-…

The abbreviations per category


abbrev inserts
render :action => “action
render :action => “action“, :layout => “layoutname
render :file => “filepath
render :file => “filepath“, :use_full_path => false
render :inline => “<%= ‘hello’ %>
render :inline => “<%= ‘hello’ %>“, :locals => { name => “value” }
render :inline => “<%= ‘hello’ %>“, :type => :rxml
render :layout => “layoutname
render :nothing => true
render :nothing => true, :status => 401
render :partial => “item
render :partial => “item“, :collection => items
render :partial => “item“, :locals => { :name => “value“}
render :partial => “item“, :object => object
render :partial => “item“, :status => 500
render :text => “Text here…
render :text => “Text here…“, :layout => “layoutname
render :text => “Text here…“, :layout => true
render :text => “Text here…“, :status => 401
render_component :action => “index
render_component :controller => “items
render_component :controller => “items“, :action => “index
redirect_to :action => “index
redirect_to :action => “show“, :id => @item
redirect_to :controller => “items
redirect_to :controller => “items“, :action => “list
redirect_to :controller => “items“, :action => “show“, :id => @item


abbrev inserts
flash[:notice] = “Text here…
logi “Text here…


abbrev inserts
belongs_to :model, :class_name => “class“, :foreign_key => “key
has_many :model, :class_name => “class“, :foreign_key => “key“, :dependent => :destroy
has_one :model, :class_name => “class“, :foreign_key => “key“, :dependent => :destroy
validates_presence_of :attr
validates_uniqueness_of :attr
validates_numericality_of :attr


abbrev inserts
create_table :name do |t|

create_table :name, :force => true do |t|

drop_table :name
t.column “name“, :type
add_column :table_name, :column_name, :type
change_column :table_name, :column_name, :type
rename_column :table_name, :column_name, :new_column_name
remove_column :table_name, :column_name
add_index :table_name, :column_name
add_index :table_name, :column_name, :index_type
remove_index :table_name, :column_name


abbrev inserts
<%= form_tag :action => “update” %>

<%= end_form_tag %>
<%= link_to “title“, :action => “index” %>
<%= link_to “title“, :action => “edit“, :id => @item %>
<%= link_to “title“, :controller => “items” %>
<%= link_to “title“, :controller => “items“, :action => “index” %>
<%= link_to “title“, :controller => “items“, :action => “edit“, :id => @item %>
<%=h @item %>
<% if cond -%>

<% end -%>
<% if cond -%>

<% else -%>
<% end -%>
<% unless cond -%>

<% end -%>
<% for elem in @list %>

<% end %>
<%  -%>
<%=  %>

And that completes this article.