credmp

Ramblings of a code junkie

February 18, 2007

Optimizing Emacs usage

Written by
core

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.

February 18, 2007

Speech recognition programming

Written by
core

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…

February 18, 2007

Taking care of tags

Written by
core

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!

February 17, 2007

OpenID going mainstream?

Written by
core

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, http://openid.aol.com/<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…

February 17, 2007

Words of advice

Written by
core

Anyone programming or thinking about programming for a company should read this story…. the soundest advice you will get :)

January 16, 2007

C++ lexicographical_compare and locales

Written by
core

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:

lt_char.hpp

#ifndef LT_CHAR_H
#define LT_CHAR_H

class lt_char {
public:
    lt_char(const char *table);

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

#endif // LT_CHAR_H

lt_char.cxx

#include "lt_char.hpp"
#include 

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];
}

lt_string.hpp

#ifndef LT_STRING_H
#define LT_STRING_H

#include 
#include 

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

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

#endif // LT_STRING_H

lt_string.cxx

#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(),
                                        lt_char(char_table));
}
December 21, 2006

Network based installation of Linux distros

Written by
core

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

December 21, 2006

Mapping software

Written by
core

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 :)

November 30, 2006

More Emacs goodness

Written by
core

Found a couple of interesting blogposts about Emacs:

November 28, 2006

Ruby On Rails and Emacs

Written by
core

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://rubyforge.org/var/svn/emacs-rails/trunk emacs-rails

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

.elisp$ wget http://www.kazmier.com/computer/snippet.el
.elisp$ http://www.webweavertech.com/ovidiu/emacs/find-recursive.txt
.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
      '(try-complete-abbrev
        try-complete-file-name
        try-expand-dabbrev))

(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")
(mmm-add-classes
 '((erb-code
    :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))
            (mmm-mode-on)))
(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]
  end

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”
  end

Shortcuts

  ((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

General

abbrev inserts
ra
render :action => “action
ral
render :action => “action“, :layout => “layoutname
rf
render :file => “filepath
rfu
render :file => “filepath“, :use_full_path => false
ri
render :inline => “<%= ‘hello’ %>
ril
render :inline => “<%= ‘hello’ %>“, :locals => { name => “value” }
rit
render :inline => “<%= ‘hello’ %>“, :type => :rxml
rl
render :layout => “layoutname
rn
render :nothing => true
rns
render :nothing => true, :status => 401
rp
render :partial => “item
rpc
render :partial => “item“, :collection => items
rpl
render :partial => “item“, :locals => { :name => “value“}
rpo
render :partial => “item“, :object => object
rps
render :partial => “item“, :status => 500
rt
render :text => “Text here…
rtl
render :text => “Text here…“, :layout => “layoutname
rtlt
render :text => “Text here…“, :layout => true
rts
render :text => “Text here…“, :status => 401
rcea
render_component :action => “index
rcec
render_component :controller => “items
rceca
render_component :controller => “items“, :action => “index
rea
redirect_to :action => “index
reai
redirect_to :action => “show“, :id => @item
rec
redirect_to :controller => “items
reca
redirect_to :controller => “items“, :action => “list
recai
redirect_to :controller => “items“, :action => “show“, :id => @item

Environment

abbrev inserts
flash
flash[:notice] = “Text here…
logi
logger.info “Text here…
par
params[:id]
ses
session[:user]

Models

abbrev inserts
bt
belongs_to :model, :class_name => “class“, :foreign_key => “key
hm
has_many :model, :class_name => “class“, :foreign_key => “key“, :dependent => :destroy
ho
has_one :model, :class_name => “class“, :foreign_key => “key“, :dependent => :destroy
vp
validates_presence_of :attr
vu
validates_uniqueness_of :attr
vn
validates_numericality_of :attr

Migrations

abbrev inserts
mct
create_table :name do |t|

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

end
mdt
drop_table :name
mtcl
t.column “name“, :type
mac
add_column :table_name, :column_name, :type
mcc
change_column :table_name, :column_name, :type
mrec
rename_column :table_name, :column_name, :new_column_name
mrmc
remove_column :table_name, :column_name
mai
add_index :table_name, :column_name
mait
add_index :table_name, :column_name, :index_type
mrmi
remove_index :table_name, :column_name

ERB

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

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

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

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

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

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

And that completes this article.

Random Links