Tag Archives: emacs

Up and running with Emacs and Git

I code in Emacs. Emacs has good support for version control tool interaction in the vc-mode package. I want to use git and have vc-mode work with git. I also want access to special git commands that the vc-mode does not export directly. The notes below are for Ubuntu Hardy, which is what I use all the time.

Install Git

First I made sure I had git installed:

$ sudo aptitude install git-core

(I use aptitude instead of apt when I want ‘recommended’ packages to be installed automatically. Basically, I am letting aptitude choose and install other packages which are not strictly needed to install git-core, but which Ubuntu/Debian packagers think might be useful for me ;-)).

Create a template python package

$ cd workspace
$ paster create hello

I am using Python paste, paste script and paste deploy tools. The documentation for these sucks. Basically, I just use paste script to create the template for a project that can be packaged with setuptools. I am also doing this in a virtualenv. More on them some other time.

I end up with this structure:

$ cd ~/workspace/hello
$ tree
.
|-- build
|   `-- lib
|       `-- hello
|           `-- __init__.py
|-- hello
|   `-- __init__.py
|-- hello.egg-info
|   |-- PKG-INFO
|   |-- SOURCES.txt
|   |-- dependency_links.txt
|   |-- entry_points.txt
|   |-- not-zip-safe
|   `-- top_level.txt
|-- setup.cfg
`-- setup.py

5 directories, 10 files

Now I can build a tarball or egg with:

$ python setup.py bdist_egg
$ python setup.py bdist

Users can take the output and install this with ‘python setup.py install’.

Initial git commit

$ git init

$ git add -a .

$ git commit # write a suitable commit message

$ git log

$ git status

Emacs+git

On ubuntu, the git-core package contains emacs support files. I just add this to my .emacs
;; -----------------------------------------------------------------------------
;; Git support
;; -----------------------------------------------------------------------------
(load "/usr/share/doc/git-core/contrib/emacs/git.el")
(load "/usr/share/doc/git-core/contrib/emacs/git-blame.el")
(load "/usr/share/doc/git-core/contrib/emacs/vc-git.el")
(add-to-list 'vc-handled-backends 'GIT)

Now, basic vc-mode works:

C-x C-f ~/workspace/hello/setup.py
C-x v l # vc-print-log
C-x v g # vc-annotate

Direct git interaction

M-x git-status

git-status-mode is the major mode for interacting with git directly. Typing h in this mode bring up a menu of commands and keybindings.

Adding a file

I add two files: hello/speaker.py and hello/main.py.  Then:

M-x git-status

Navigate to speaker.py and main.py and type ‘a’ (for git-add-file) on both.

Type ‘c’ (for git-commit-file). Type in a log message and C-c C-c to finish the log message and commit.

Adding files to gitignore

I create a .gitignore file in the top level directory of my project and put this in it:

*.egg
*.pyc
*~

Now I go back to my git-status window and press g (git-status-refresh), and et voila, the clutter disappears.

Committing changes

However, I notice that the hello/main.py is marked as ‘Added’ but not Uptodate. What gives? It seems git-commit-file commits only one file. Oops.  What I should have done is what I do now:

  • ‘M’ to mark all files (.gitignore and hello/main.py)
  • c to commit all files. (Type in log message)
  • g to refresh. (Shows ‘No changes’ and no files are listed)
  • t u (git-toggle-show-uptodate; now lists all files, even those which are uptodate)
  • q (git-status-quit)

Diffing changes

I edit main.py and speaker.py. Going to git-status, and pressing ‘=’ over a file gives me the diff against the committed version.

I can also mark multiple files with ‘m’, or all files with ‘M’. Now pressing ‘=’ diffs all those files.

Committing selected changes

Let’s say I’ve added a bunch of code to some files that I want to commit. I’ve also toggled a gloabl DEBUG variable to aid in my own testing, and I don’t want to commit that particular change. In subversion or cvs I’d have to ensure that the flag was set to its proper state and then commit the whole thing together. However in git, I can commit some changes (patches) and ignore others. This cannot be done from within emacs though. I have to switch to the command line and do a ‘git add –interactive’, which gives me a menu system to add selective ‘hunks’.

Back to the command line, I do a git diff –cached to see what I am going to commit. I don’t like it. I want to start choosing the changes I want to commit again:

  • git reset –mixed (reset the index)
  • git add -i (choose what to add, again)
  • git diff –cached (see what I am gonna be committing0
  • git diff (see what else is there in my WC that I have not scheduled to be committed)
  • git commit (type log and commit)

Note:

Working of git-reset and git-diff

Working of git-reset and git-diff

Advertisements

Up and running with Emacs, Erlang, and Distel

Umm… did I mention that I yearn for hacking Erlang code, too? Following Bill Clementson’s lead, I set up  Emacs+Erlang on my Ubuntu hardy box.

Step 1: Install erlang and erlang-mode

I used the version of erlang and erlang-mode for emacs in Ubuntu’s repositories. I might come to regret it some day, but for now the following was just too simple to resist:

$ sudo aptitude install erlang
# The above will install erlang-mode too;
# if it does not just "apt-get install erlang-mode"

Step 2: Configure erlang-mode in Emacs

I just put the following in my .emacs:

;; Erlang-mode
(require 'erlang-start)
(add-to-hook 'erlang-mode-hook
             (lambda ()
            ;; when starting an Erlang shell in Emacs, the node name
            ;; by default should be "emacs"
            (setq inferior-erlang-machine-options '("-sname" "emacs"))
            ;; add Erlang functions to an imenu menu
            (imenu-add-to-menubar "imenu")))

Now I can launch Emacs and open an erlang file, which puts me in Erlang mode.  I can start and Erlang shell with “C-c C-z”, compile the Erlang code with “C-c C-k”, and view the compilation result in the Erlang buffer (if the buffer is hidden) with “C-c C-l”.  Or, I can just switch to the Erlang shell with “C-c C-z”.  The customizations above enable me to get a menu item in the Emacs menubar with a list of functions defined in the file I am visiting, which is a big help. I am used to “ecb-mode” when coding Python; ECB does not grok Erlang yet, so the imenu is a handy substitute when coding Erlang.

Step 3: Install Distel

Distel is to Erlang and erlang-mode what SLIME is to Lisp and lisp-mode.

To get distel:

$ cd ~/.emacs.d/
$ svn co http://distel.googlecode.com/svn/trunk/ distel
$ cd distel
$ make
$ cd doc
$ make postscript && make postscript # must run twice
$ make info && sudo make install # install the Info documentation
$ info distel # read the distel info documentation

Step 4: Configure Emacs to use Distel

I just need to put this in my .emacs:

(push "/home/parijat/.emacs.d/distel/elisp/" load-path)
(require 'distel)
(distel-setup)

Step 5: Configure Erlang

Distel is designed to work in a distributed Erlang system. It can connect to specified Erlang nodes. My strategy is to use the standard erlang-mode command “C-c C-z” to start an Erlang shell, and connect to it using Distel by “C-c C-d n”. The latter asks for a nodename, which is going to be “emacs@beowulf” (because beowulf is the short hostname of my laptop).

But before we start using remote Erlang nodes, we should create on each physical machine that we will use a ~/.erlang.cookie file with a password, for inter-Erlang node authentication:

$ echo "secret" > ~/.erlang.cookie
$ chmod 0400 ~/.erlang.cookie

Step 6: Play with Distel

So, now we can launch an Erlang node, either via Emacs using “C-c C-z”, or on the command line using “erl -sname mynode”. Then, from within Emacs, we can connect Distel to this node using “C-c C-d n” specifiying the nodename on the prompt. Now we can ask Distel to interrogate the Erlang node for various things.

C-c C-d l ; list erlang processes
PID/Name              Initial Call                              Reds     Msgs
init                  otp_ring0:start/2                         3821        0
erl_prim_loader       erlang:apply/2                           87239        0
error_logger          proc_lib:init_p/5                          229        0
application_controlle erlang:apply/2                            2501        0
<0.7.0>               proc_lib:init_p/5                           45        0
<0.8.0>               application_master:start_it/4               91        0
kernel_sup            proc_lib:init_p/5                         1498        0
rex                   proc_lib:init_p/5                          493        0
global_name_server    proc_lib:init_p/5                           69        0
<0.12.0>              erlang:apply/2                              25        0
<0.13.0>              erlang:apply/2                               4        0
<0.14.0>              erlang:apply/2                               3        0
inet_db               proc_lib:init_p/5                          129        0
net_sup               proc_lib:init_p/5                          312        0
erl_epmd              proc_lib:init_p/5                          147        0

									

Up and running with Emacs, sbcl, and SLIME

While I normally program in Python, a part of me wants to quickly hack some lisp code every now and then. Especially during those long minutes when my automated tests are running.

I realized that long neglect had left me without a working lisp setup. Here is how I got it up and running again.

Step 1: Get rid of system lisp and slime

The version of sbcl and SLIME in my Ubuntu system is not recent enough for my liking. So I get rid of them:

$ sudo apt-get -y remove sbcl slime common-lisp-controller
$ sudo apt-get -y autoremove # get rid of packages we don't need anymore
$ sudo rm -rf /var/cache/common-lisp-controller

Step 2: Install common requirements

cd ~/
sudo apt-get update
sudo apt-get -y install emacs22
sudo apt-get -y install cvs
sudo apt-get -y install git-core
sudo apt-get -y install darcs
sudo apt-get -y install subversion
sudo apt-get -y install build-essential
sudo apt-get -y install autoconf
sudo apt-get -y install curl
sudo apt-get -y install sbcl
sudo apt-get -y install texinfo
sudo apt-get -y install tetex-bin
sudo apt-get -y install xloadimage

Step 3: Get clbuild

$ mkdir lisp
$ cd lisp
# for fresh install of clbuild
$ darcs get http://common-lisp.net/project/clbuild/clbuild
$ cd clbuild
# Or, to update existing clbuild
$ cd clbuild
$ darcs pull

Step 4: Get latest SBCL

$ ./clbuild update sbcl
$ cd source/sbcl
$ sh make.sh
$ cd doc/manual
$ make
$ cd ../..
$ echo > ~/.sbclrc
(require :asdf)
(push "/home/parijat/lisp/clbuild/systems/" asdf:*central-registry*)
^D
$

Step 5: Setup SLIME

$ ./clbuild update slime

Now, we need to add this slime configuration to our .emacs file:

(push "/home/parijat/lisp/clbuild/source/slime" load-path)
;; Common Lisp Mode
(setq inferior-lisp-program "/usr/local/bin/sbcl")
(add-to-list 'auto-mode-alist '("\\.lisp$" . lisp-mode))
(add-to-list 'auto-mode-alist '("\\.cl$" . lisp-mode))
(add-to-list 'auto-mode-alist '("\\.asd$" . lisp-mode))
(require 'slime)
(slime-setup)
(eval-after-load "slime"
 '(progn
    (setq slime-complete-symbol*-fancy t
          slime-complete-symbol-function 'slime-fuzzy-complete-symbol
          slime-when-complete-filename-expand t
          slime-truncate-lines nil
          slime-autodoc-use-multiline-p t)
    (slime-setup '(slime-fancy slime-asdf))
    (define-key slime-repl-mode-map (kbd "C-c ;")
      'slime-insert-balanced-comments)
    (define-key slime-repl-mode-map (kbd "C-c M-;")
      'slime-remove-balanced-comments)
    (define-key slime-mode-map (kbd "C-c ;")
      'slime-insert-balanced-comments)
    (define-key slime-mode-map (kbd "C-c M-;")
      'slime-remove-balanced-comments)
    (define-key slime-mode-map (kbd "RET") 'newline-and-indent)
    (define-key slime-mode-map (kbd "C-j") 'newline)))
(add-hook 'lisp-mode-hook (lambda ()
                           (cond ((not (featurep 'slime))
                                  (require 'slime)
                                  (normal-mode)))
                           (indent-tabs-mode nil)
                           (pair-mode t)))

Note: pair-mode is a nice package for inserting balanced parentheses, quotes, braces and square-brackets, etc., which I installed earlier by hand.

Now we can launch emacs, and start slime with “M-x slime”.

Caveat

For some reason, after doing the above, slime would still not start. Doing a “M-x slime” would throw me into the sbcl debugger with the error message that sbcl could not find “/usr/share/common-lisp/systems/slime/swank-loader.lisp”, or something like that (I could be wrong about the exact path). After much head-scratching (and grepping my ~/lisp directory), I figured out I had to change the emacs customization variable slime-backend. This can be done by doing “M-x customize-group RET slime-lisp RET” and changing the value of “Slime Backend” to simply “swank-loader.lisp” (the file should be in the same directory as “slime.el”). We can also give an absolute path to the file. I found that the value of this variable was set wrongly (an artifact of using apt-get installed slime, I guess) and hence sbcl was not able to load the correct file.

Post a blog entry from within emacs #1

This is my first entry from within emacs.

Let’s see… can I put HTML tags in it?

if code == 'FORMATTED_PROPERLY':
   parijat = 'Happy'

;; —————————————————————————–
;; Web logger
;; —————————————————————————–
(add-to-list ‘load-path “~/.emacs.d/weblogger”)
(requireweblogger)

Typing accented/european characters in Emacs

Normally I never have to type anything but ASCII in Emacs. But I have been doing some internationalization testing/development, and now and then need to type some non-ASCII characters. Right now, I am happy to be able to type accented characters, though the ultimate goal is to be able to type in a wide variety of languages.

To get emacs to display most languages and scripts:

  • I ensure than my LANG environment is UTF-8
  • I install xfonts-intl-* and emacs-intl-fonts packages
  • I do a `C-h h’ to see the multilingual hello file…. the languages of my interest should be present there

To type `interesting’ characters in Emacs, I have found that this works:

  • Change input method to RFC1345 by:

    C-x RET C-\ RET (select default input method RFC1345)

  • Type an accented chanracter using its RFC1345 mnemonic. E.g., to type the inverted exclamation mark used in Spanish I would type “&!I” (makes sense: ‘&’ introduces the special character, ! is the excalamation mark, and I inverts it).

To be able to quickly lookup the RFC, I installed the `doc-rfc’ meta-package. Now, to read RFC3412, for example, I do:


C-x C-f /usr/share/doc/RFC/links/rfc3412.txt.gz

and since I have installed the `emacs-goodies-el’ package, which contains `rfcview’, the RFC shows up nicely formatted in Emacs.

My First Emacs Lisp Function


(defun how-many-chars ()
(interactive)
(message "We are %d chracters into this buffer."
(- (point)
(save-excursion
(goto-char (point-min))
(point)))))

GNU Emacs, SLIME, Allegro

For some reason, I decided that I just had to switch to GNU Emacs from XEmacs on my WinXP laptop. So I went and downloaded Emacs 22.1 for Windows and installed it.

Setting it up for Erlang was easy: I added this to C:\Documents and Settings\Parijat\.emacs:


;; Erlang:
;; Add the location of the elisp files to the load-path
(setq load-path (cons "C:/erl5.5.4/lib/tools-2.5.4/emacs" load-path))
;; set the location of the man page hierarchy
(setq erlang-root-dir "c:/erl5.5.4")
;; add the home of the erlang binaries to the exec-path
(setq exec-path (cons "c:/erl5.5.4/bin" exec-path))
;; load and eval the erlang-start package to set up everything else
(require 'erlang-start)

Now, to setup Common Lisp. I use Allegro CL 8.0 Free Express Edition. (Yes, one day I’ll buy the full version and repay Franz, but only after getting myself Lisp Certified ;-)) I was following the instructions at http://www.franz.com/emacs/slime.lhtml and http://common-lisp.net/project/asdf-install/tutorial/setup.html .

This is what I did:

1. Opened up ACL and loaded asdf into it:


International Allegro CL Free Express Edition
8.0 [Windows] (Aug 17, 2007 22:59)
Copyright (C) 1985-2006, Franz Inc., Oakland, CA, USA. All Rights Reserved.

This development copy of Allegro CL is licensed to:
Trial User

CG version 1.81.2.23 / IDE version 1.80.2.21
Loaded options from C:\Documents and Settings\Parijat\My Documents\allegro-prefs.cl.

;; Optimization settings: safety 1, space 1, speed 1, debug 2.
;; For a complete description of all compiler switches given the current optimization settings
;; evaluate (EXPLAIN-COMPILER-SETTINGS).

[changing package from "COMMON-LISP-USER" to "COMMON-GRAPHICS-USER"]
CG-USER(1): (require :asdf)
; Fast loading C:\Program Files\acl80-express\code\ASDF.001
T

2. Then, downloaded asdf-install and unpacked it into “C:\Documents and Settings\Parijat\asdf-install” (the source tarball has several nested directories called asdf-install; the innnermost contains the .asd file, and that’s the one I am referring to here).

3. Told asdf about this directory:

CG-USER(4): (pushnew "c:/Documents and Settings/Parijat/asdf-install/" asdf:*central-registry* :test #'equal)

and compiled and loaded asdf-install:

CG-USER(5): (asdf:operate 'asdf:compile-op 'asdf-install)
CG-USER(6): (asdf:operator 'asdf:load-op 'asdf-install)

4. Well, all this stuff was in the end to get SLIME. I went to http://common-lisp.net/project/slime/#downloading and found the link to the latest SLIME. Now, on Windows, it seems asdf-install can’t download and install tarballs off net (at least on Allegro CL). Then I downloaded and put the slime tarball in C:\Temp. Then:

(setq asdf-install::*verify-gpg-signatures* nil)
(setq *cygwin-bash-program* "c:/cygwin/bin/bash.exe")

and then:


CG-USER(7): (asdf-install:install "C:/Temp/slime-2.0.tgz")

This did not work, complaining:


Warning: Cannot find tar command "C:\\PROGRA~1\\Cygwin\\bin\\bash.exe".
Error: Unable to extract tarball C:/Temp/slime-2.0.tgz.

It seems my mod to *cygwin-bash-program* did not take effect inside asdf. Wonder why. I even quit Allegro, restarted it, defined *cygwin-bash-program* before compiling and loading asdf-install. No luck. (One thing I did not try was to define asdf-install:*cygwin-bash-program* instead of vanilla *cygwin-bash-program*). So I just went and hardcoded tar-command() in installer.lisp to return “C:\\cygwin\\bin\\bash.exe”.

Now the above command works.

5. The Franz documentation instructs me to start “mlisp.exe” or “alise.exe” LISP image (see next step). But my ACL 8.0 express did not come with these images; it only has “allegro-ansi.exe”. So, following the README in the acl80-express directory, I create the images, by starting allegro-ansi.exe, and in the “Debug window”, typing the following:

CG-USER(1): (build-lisp-image "sys:mlisp.dxl" :case-mode :case-sensitive-lower
:include-ide nil :restart-app-function nil
:restart-init-function nil)
CG-USER(2): (sys:copy-file "sys:allegro-ansi.exe" "sys:mlisp.exe")

Now, I have a mlisp.exe and mlisp.dxl. Sure enough, clicking on mlisp.exe launches a console LISP without the GUI.

6. Now I have to load slime into Emacs. According to the instructions on the Franz webpage, I created a file “C:\Documents and Settings\Parijat\.slime.lisp”, with the contents:

(load "C:/Documents and Settings/Parijat/.asdf-install-dir/site/slime-2.0/swank-loader.lisp")

(sys:with-command-line-arguments (("p" :short port :required)
("ef" :long ef :required))
(restvar)
(swank::create-server :port (parse-integer port :junk-allowed nil)
:style :spawn
:dont-close t
:coding-system (or ef "latin-1")))

and added this to my .emacs:

;; Allegro LISP + SLIME
(push "c:/Documents and Settings/Parijat/.asdf-install-dir/site/slimw-2.0/" load-path)
(require 'slime)
(slime-setup)

(setq slime-multiprocessing t)
(setq *slime-lisp* "C:/Program Files/acl80-express/mlisp.exe")
(setq *slime-port* 4006)

(defun slime ()
(print "this is my slime")
(interactive)
(shell-command
(format "%s +B +cm -L \"c:/Documents and Settings/Parijat/.slime.lisp\" -- -p %s --ef %s &"
*slime-lisp* *slime-port*
slime-net-coding-system))
(delete-other-windows)
(while (not (ignore-errors (slime-connect "localhost" *slime-port*)))
(sleep-for 0.2)))

I restart emacs. I say “M-x slime”. And wait. The mlisp.exe window shows up, but no connection.

I figure that the problem is in (swank:create-server :port …) which is supposed to start the swank server, does not work. If I run it in the mlisp.exe window, the command does not return (okay, maybe it is not supposed to). I can’t telnet to port 4006 on the localhost, though.

Puff!!! It used to be simpler.

Emacs and bitstream fonts

I use emacs on Ubuntu heavily and naturally want a nice font to use. I chose to use the “bitstream vera sans mono” font. Well, easy does it: Options->Customize Emacs->Specific Face: “default”, and setting the value of “Font Family” to “bitstream-bitstream vera sans mono” and value of “Height” to “100” gave me the nice font that I wanted. “Custom” created the settings for me:

(custom-set-faces
;; custom-set-faces was added by Custom — don’t edit or cut/paste it!
;; Your init file should contain only one such instance.
‘(default ((t (:inherit nil :stipple nil :background “gray12” :foreground “green” :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :height 117 :width normal :family “bitstream vera sans mono”)))))

I should mention that I am using the “color-scheme” package and using a nice looking color scheme. The color information probably comes from there.

But then I tried to create a new frame (C-x 5 2) and lo! the new frame had my old font. Reading the emacs faq gave the answer: I’d have to set the font again in the variable that determines the options for all new frames. So I set in my “~/.emacs”:

(setq default-frame-alist
‘((font . “-bitstream-bitstream vera sans mono-medium-r-normal–0-0-0-0-m-0-iso8859-1”)))

and new frames would now have the specified font, which happens to be the same as the original. I wonder if it is a coincidence that the size of the font in new frames and initial matches, because I have not specified the height of the font in this variable.

This seems like a ugly way: why specify the font properties in two different places? So I commented out the face created by custom, and oops! new frames would have a background of white. So I had to undo the change and let the fonts be specified in two places. But at least the initial and new frames have the same good looking font.