Posts Tagged ‘emacs’

Emacs Fixes

Monday, September 28th, 2009

This will be amassed post in the vein of this one. I amassed enough changes to my already blogged-about improvements to emacs to go over what I changed. When possible, I’ll link to previous blog posts about them; In some cases I have just minor additions that aren’t big enough to go in their own post.

Hooks are quite nice, but they have some problems with lambda functions. Lambdas in hooks cannot be removed easily or modified; you’ll have to modify the hook variable manually in order to remove or modify that function. After having to play around with many of my hooks, I got tired of setting hook variables to nil and re-adding everything so I changed many of my hooks that used lambdas to instead be defined as regular functions. A list of some of these is below:

(defun turn-on-visual-line-mode ()
  (interactive)
  (visual-line-mode 1))
(add-hook 'text-mode-hook 'turn-on-visual-line-mode)
 
(defun c-mode-common-hook-fn ()
  (interactive)
  (c-toggle-syntactic-indentation 1)
  (setq c-basic-offset 4)
  (c-toggle-hungry-state 1)
  (c-toggle-electric-state 1)
  (flymake-mode 1))
 
(add-hook 'c-mode-common-hook 'c-mode-common-hook-fn)
(add-hook 'c-mode-common-hook 'yas/minor-mode-on)
(add-hook 'c-mode-hook 'c-turn-on-eldoc-mode)

I also started interpreters for most of the languages I have customizations for, so I decided that Python should be no exception. The following code snippet will open a python interpreter as a new buffer.

(python-switch-to-python t)

I also made yet another change to ido-goto-symbol. This function will prompt the user, using ido, for a function in the current file to move to and will then move point to the definition of the function. I updated it so that if the point is on a function name, that name will appear first in the list of options (and thus be the default choice).

(defun ido-goto-symbol ()
  "Will update the imenu index and then use ido to select a symbol to navigate to"
  (interactive)
  (imenu--make-index-alist)
  (let ((name-and-pos '())
        (symbol-names '()))
    (flet ((addsymbols (symbol-list)
                       (when (listp symbol-list)
                         (dolist (symbol symbol-list)
                           (let ((name nil) (position nil))
                             (cond
                              ((and (listp symbol) (imenu--subalist-p symbol))
                               (addsymbols symbol))
                              ((listp symbol)
                               (setq name (car symbol))
                               (setq position (cdr symbol)))
                              ((stringp symbol)
                               (setq name symbol)
                               (setq position (get-text-property 1 'org-imenu-marker symbol))))
                             (unless (or (null position) (null name))
                               (add-to-list 'symbol-names name)
                               (add-to-list 'name-and-pos (cons name position))))))))
      (addsymbols imenu--index-alist)
      (let* ((symbol-at-point (symbol-name (symbol-at-point)))
             (selected-symbol (ido-completing-read
                               "Symbol? "
                               (if (member symbol-at-point symbol-names)
                                   (cons symbol-at-point (remove-if (lambda (x) (string-equal x symbol-at-point))
                                                                    symbol-names))
                                 symbol-names)))
             (position (cdr (assoc selected-symbol name-and-pos))))
        (if (markerp position)
            (goto-char position) (goto-char (overlay-start position)))))))

I talked about my methods to update dired here. In the comments was a suggestion to just use auto-revert-mode. This greatly simplifies the code for this functionality, and solves some of the issues I mentioned in that post, so I now use it instead for dired buffers.

(defun turn-on-auto-revert-mode ()
  (interactive)
  (auto-revert-mode 1))
 
(add-hook 'dired-mode-hook 'turn-on-auto-revert-mode)

ff-find-other-file will go to a ‘matching’ file in a C or C++ buffer. If on a #include line, it will open the file being included; otherwise, if you are in a header file it will go to the corresponding implementation file and go to the corresponding header if you are in an implementation file. This is quite useful, so it now has it’s own keybinding.

(define-key	 c-mode-base-map (kbd "C-c o") 'ff-find-other-file)

I ended up changing the implementation of my auto-indentation functions. I moved the list of major-modes that this would be active in to a new list which both yank and yank-pop check. Also in the comments of that post was a suggestion to advise kill-line instead of replacing it, and the advice works quite well so I am now using it.

(defvar programming-major-modes
  '(emacs-lisp-mode scheme-mode lisp-mode c-mode c++-mode objc-mode latex-mode plain-tex-mode
                    java-mode)
  "List of programming modes")
 
(defadvice yank (after indent-region activate)
  (if (member major-mode programming-major-modes)
      (let ((mark-even-if-inactive t))
        (indent-region (region-beginning) (region-end) nil))))
 
(defadvice yank-pop (after indent-region activate)
  (if (member major-mode programming-major-modes)
      (let ((mark-even-if-inactive transient-mark-mode))
        (indent-region (region-beginning) (region-end) nil))))
 
(defadvice kill-line (after fixup-whitespace activate)
  "Call fixup-whitespace after killing line."
  (save-excursion
    (if (looking-back "^\s*")
        (funcall indent-line-function)
      (fixup-whitespace))))

I also added a few new keybindings. I recompile frequently, so a keybinding for it seems appropriate. So does shortening the keybinding for goto-line.

(global-set-key (kbd "<f2>") 'recompile)
(global-set-key (kbd "M-g") 'goto-line)

The last improvement I have is yet another change to imenu-java-generic-expression. I’m still waiting for the FSF to get my copyright assingment forms so that this becomes a part of emacs proper, but until then I updated the regexp to work with functions that throw Exceptions as well.

(defun set-java-generic-expression ()
  (setq imenu-generic-expression
        `((nil
           ,(concat
             "[" c-alpha "_][\]\[." c-alnum "_<> ]+[ \t\n\r]+" ; type spec
             "\\([" c-alpha "_][" c-alnum "_]*\\)" ; method name
             "[ \t\n\r]*"
             ;; An argument list htat is either empty or contains any number
             ;; of arguments.  An argument is any number of annotations
             ;; followed by a type spec followed by a word.  A word is an
             ;; identifier.  A type spec is an identifier, possibly followed
             ;; by < typespec > possibly followed by [].
             (concat "("
                     "\\("
                     "[ \t\n\r^M]*"
                     "\\("
                     "@"
                     "[" c-alpha "_]"
                     "[" c-alnum "._]""*"
                     "[ \t\n\r^M]+"
                     "\\)*"
                     "\\("
                     "[" c-alpha "_]"
                     "[\]\[" c-alnum "_.]*"
                     "\\("
 
                     "<"
                     "[ \t\n\r^M]*"
                     "[\]\[.," c-alnum "_<> \t\n\r^M]*"
                     ">"
                     "\\)?"
                     "\\(\\[\\]\\)?"
                     "[ \t\n\r^M]+"
                     "\\)"
                     "[" c-alpha "_]"
                     "[" c-alnum "_]*"
                     "[ \t\n\r^M,]*"
                     "\\)*"
                     ")"
                     "[.," c-alnum " \t\n\r^M]*"
                     "{"
                     )) 1))))
 
(add-hook 'java-mode-hook 'set-java-generic-expression)

That’s all for today - if you have any additional remarks, let me know in the comments.

Emacs-Vc

Friday, September 25th, 2009

Emacs has integrated version control support for numerous VC backends, including Git and Perforce. It gives a set of generic commands that you can use to interact with each version control system the same way. I’ve been using this for vc commands that don’t involve submitting or changelists. Modifying changelists I just do through a shell buffer, and I tend to go to an external shell to do commits, and I haven’t ever gotten emacsclient working properly.

The emacs package that synchronizes with The following is just a list of some of the more useful VC functions. I don’t use all of them, but a lot of them I do and I should probably use the others more than I do. Many of them have keybindings, which are suggested when you perform the command with M-x. Since Perforce is non-free, Emacs doesn’t come with a wrapper for it, but you can download them from here.

vc-annotate - This will display the current file in a new buffer. This buffer will have the revision each line came from, and the user who added that line. Additionally, the buffer will be color-coded according to how old lines are.

vc-annotate-find-revision-at-line - When in a buffer generated from vc-annotate, this will create a buffer containing the contents of the file at whatever revision the current line came from.

vc-annotate-show-changeset-diff-revision-at-line - When in vc-annotate, this will show the diff of the checkin that added the current line.

vc-annotate-show-diff-revision-at-line - When in vc-annotate, this will shown the diff *for this particular file* of the checkin that added the current line.

vc-annotate-show-log-revision-at-line - When in vc-annotate, this will show the checkin message for the commit that added the current line.

vc-create-repo - This will prompt you for a type of repository (svn, bzr, git, etc) and create a new repository in the current directory.

vc-delete-file - This will delete a file and remove it from the repos - for example, it will issue a ’svn rm’.

vc-diff - This will open a buffer containing a diff of the current file with the current file at last revision.

vc-dir - This will show the status of files in the prompted directory in a new buffer. It will tell you which files are unregistered, edited, or added - files in the repository that have not been changed seem to not be displayed. This is much like a ’svn status’ command.

vc-merge - This will merge changes between revisions/branches, bound to C-x v m.

vc-next-action - This will perform what it thinks the next action will be. If in an unchecked file, it will add it to the repos. If you’ve edited the file, it will perform a checkin on that file.

vc-print-log - This will open a buffer with all the checklist comments that apply to the current file.

vc-register - This will add a file to the version control system in the directory - will perform a ’svn add’, ‘p4 add’, etc.

vc-rename-file - This command renames a file in the version control.

vc-resolve-conflicts - vc-resolve-conflicts invokes ediff to resolve conflicts for the current file.

vc-revert - This will revert the current file, losing all changes you’ve made since the last checkin.

vc-revision-other-window - This asks for a revision and then displays that revision of the current file in another window.

vc-update - This will update your copy of the repository to the current status . Essentially, performs a ’svn up’ or ‘p4 sync’.

vc-version-diff - This will prompt for two revisions of the current file and display the diff of those two revisions.

More Emacs Refatorings

Monday, September 21st, 2009

I ended up performing a few more refactorings to my initialize code in order to make it work a bit better, so I thought I’d share them with you. The first is adding another subdirectory to my customizations directory, so the tree of my .emacs.d directory in svn looks like:

~/emacs.d/
        customizations/http://nflath.com/wp-admin/post.php?action=edit&post=377
                1/
                2/
        documentation/
        java-libraries/
        major-modes/
        minor-modes/
        utilities/

This allows me to have finer control over the order in which my customizations execute. Mainly, almost every file is in directory customizations/1/: the only one that is in customizations/2 is state.el, which will open all previously visited files. I want this to happen after my hooks have been added to modes so the buffers are set up how they should be; this wasn’t quite happening with one directory. This does mean my init.el file now has these two lines in it to load the two directories in the proper order:

(setq customizations-directory-load-times-1 (load-directory "~/.emacs.d/customizations/1/"))
(setq customizations-directory-load-times-2 (load-directory "~/.emacs.d/customizations/2/"))

I also removed several directories from my version control repository, although they are in myt actual .emacs.d repository. Specifically, the slime, clojure, clojure-contrib, swank-clojure, and emacs-w3m folders are all gone from SVN. However, since I still want these accessible from wherever I check out, I added a few lines to clojure.el and w3m-cust.el to create these files if they don’t exist:

(if (not (file-exists-p (concat clojure-src-root "/clojure")))
    (clojure-install))
 
(if (not (file-exists-p "~/.emacs.d/emacs-w3m/"))
    (let ((default-directory "~/.emacs.d/"))
      (shell-command-to-string
       "cvs -d :pserver:anonymous@cvs.namazu.org:/storage/cvsroot co emacs-w3m")
      (let ((default-directory "~/.emacs.d/emacs-w3m/"))
        (add-to-list 'load-path default-directory)
        (normal-top-level-add-subdirs-to-load-path))))

Essentially, the first time I start emacs on a new checkout, clojure-install will be run, retrieving all the files I need to start editing Clojure files. The same thing happens with emacs-w3m: If the directory doesn’t exist, it is checked out and the directories are added to the load-path. This can take a while, but I’d have to check the directory out anyway, and this allows for a much easier package update. I also ended up updating clojure-mode.el itself, which is checked into version control.

C-eldoc-mode

Friday, September 18th, 2009

I’ve talked about eldoc in the past, a minor mode that displays arguments to functions in the echo area. Eldoc is mainly used for lisp and scheme files, although it also works with Python, but something fewer people realize is that there is a mode that turns eldoc on for C files.

Unfortunately, this package does not come built in to GNU Emacs. You can obtain it here and put it in your load path. It doesn’t work with C++ files; only straight C files can take advantage of it. This is better than nothing, anyway. Enabling it is quite simple: Add c-eldoc.el to your load path and add the following to your initialization file:

(require 'c-eldoc)
(add-hook 'c-mode-hook 'c-turn-on-eldoc-mode)

Perforce

Friday, September 11th, 2009

My work uses perforce for source control, so I ended up having to install perforce integration for emacs. I’m pretty OK with this, since Perforce is so far my favorite version control system. I would like it if perforce allowed at least some functionality when not connected to the network, but I really prefer the interface of p4 to git or svn. As it is, Perforce is required to be able to connect to the central repository in order to do anything.

If you are using perforce, it’s probably for work, in which case they’ll probably have a guide on setting up your client. I don’t actually know a huge amount about setting perforce up: the places I’ve worked that use it have had it pre-set-up, so creating a repository and connecting to it may be ridiculously hard, but using it is quite easy.

Perforce has a very large number of commands; to see the full list, you can type ‘p4 help commands’. Fortunately, you won’t ever need to use most of those. There’s a pretty core group of about ten commands that I end up using frequently, which I’ll describe in a minute; the rest you can look up as you need to find out how to do something. Perforce also has a graphical interface you can use if you prefer that, but I find the command-line much easier. The commands I tend to use most are:

p4 add - This command will add a file to the repository. Before adding files, the version control system has no notion of it, so make sure to add all necessary files before committing.

p4 change - This command allows you to create a changelist. A changelist is a collection of files that you can commit together - basically it allows you to create groups of files that can be operated on. When you execute ‘p4 change’, a screen much like the ‘p4 submit’ screen will pop up, and you can edit the description and delete lines corresponding of files to remove them from the changelist that will be created.

p4 delete - This command deletes a file from the repository. Unlike p4 obliterate, history is kept of this file, but you do need to actually ‘p4 delete’ files that should not be checked out instead of just ‘rm’ing them.

p4 diff - p4 diff allows you to diff either a file on your workspace against a revision of that file in the repository, or two different repository revisions.

p4 edit - p4 edit will open up a file that currently exists in the repository for editing. The next time you do a p4 submit, the edited file will be in the list of files to submit.

p4 help - Perforce’s help command will let you know more about the system and commands. If you want more info about a command, ‘p4 help ‘ will give you the documentation for that command. ‘p4 help commands’ lists every perforce command. Other than that, you can just browse through the help categories by reading the options under ‘p4 help’.

p4 move - This command moves a file that is opened either for edit or add in your repository. ‘p4 rename’ will describe how to use this function.

p4 opened - This command will list every file you currently have opened. Similar to ’svn status’ for subversion, you can use it to ensure that every file has been added to the repository before committing.

p4 resolve - This command is used to resolve conflicts that occur when syncing. Resolving is always annoying, but this does what it can in order to be able to resolve conflicts. You can edit the file to remove them, accept either version of the file, and other options that are described when you use this command.

p4 revert - The standard version-control ‘revert’ command, this will undo changes to one or many files.

p4 submit - This command is used to submit your changes to the repository. When you type submit, you’ll receive a list of opened files that will be committed. Unlike SVN, deleting files from this list will prevent them from being committed. You can then type in a description of changes and exit and the commit will be pushed to the repository. You can also submit specific changelists, with ‘p4 submit -cl ‘. This will submit the changelist with the description of the changelist as the description of the commit.

p4 sync - The equivalent of ’svn up’, this will pull all the changes made to the repository since you last synced. This can require doing some resolving, which is done with ‘p4 resolve’. This can be a pain, but if you sync frequently you shouldn’t get very many conflicts.

Of course, to be maximally efficient you want to use Perforce directly from your editor. Vim, Emacs, and Eclipse all have ways to do this. In Emacs, you need to find an external elisp file for this. There are two main options for using perforce in emacs: p4.el and vc-p4.el. P4.el is more powerful - for example, it can operate on groups of files - but vc-p4.el contains hooks for emac’s usual source control actions, like vc-next-action. Both are compatible with each other, and you can use vc-p4 for most things while dipping into p4 for the difficult options. Personally, I only use p4.el, since I also don’t like Emacs’ version control integration too much for reasons I’ll talk about in another blog, and so the setup for me is simple. You download p4.el from here and put it in your load path, and then add the following to your initialization file:

(require 'p4)

All of the commands that you can use in this package are prefixed by p4, and are usually just p4-commandname. For example, to do a submit from emacs is just ‘p4 submit’. Also, most of the commands have keybindings that are ‘C-x p ‘ followed by the first letter of the name - so to add a file you would do ‘C-x p a’, edit is ‘C-x p e’ etcetera. There are a few exceptions, such as ‘p4-diff’ being ‘C-x p =’, but for the most part the keybindings are quite logical. You can look at this keybindings by doing M-x describe-function on the function you want, which tells you what the function does and any keybindings it has.

I haven’t installed vc-p4.el, but you can look at the emacs-wiki page here to see how to set it up.

js2-mode

Wednesday, September 9th, 2009

I’ve started having to do some javascript editing with Emacs for work, and so I installed Steve Yegge’s js2-mode. You can read his description of the mode here. His description is fairly extensive, so you should probably read it instead of or in addition to mine. The small amount I’ve used it has made me like it more than most programming modes Emacs has.

js2-mode, unlike most other modes, comes with a javascript parser. This allows it to know much more about the code, since it can pull eclipse-like tricks of highlighting errors and warnings in your code. Flymake-mode does this for other languages, but it’s not nearly as well integrated as js2-mode’s system. If you have an error, the code causing the error is underlined in red with a message in the minibuffer when your point is over it; if a warning, underlined in orange. This is incredibly useful.

js2’s indentation is more like python-mode’s indentation than cc-mode. It isn’t customizable, which hasn’t so far come up as a problem for me, but if you have very strict code style guidelines you may have to do some indenting manually. It provides several options for cycling through possible indentations, and one of them is usually right. Still, it can be somewhat irritating that it doesn’t just indent correctly all the time.

js2 does a few other things that are quite nice. Pressing enter inside a string will extend it to the next line, which is pretty much always what I want to do. I haven’t used it very much - I’ve mostly just been doing very like editing with it - but it is very customizable through the customize mechanism. It also supports hiding of blocks, which I don’t tend to use, but to each their own.

js2-mode is going to be built-in to GNU Emacs 23.2, but if you don’t want to wait until then to use it you have to download and enable it yourself. To enable js2-mode in your emacs, first you must download and byte-compile js2.el from here. If you don’t byte-compile the file, you’ll have to set js2-mode-must-byte-compile to nil in order for it to work at all, but byte compiling the file will make it work much faster. Once that is done, put the following lines in your initialization file to start js2-mode for all .js files:

(autoload 'js2-mode "js2" nil t)
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))

Dirtrack-mode

Saturday, September 5th, 2009

Emacs has two main ways of changing the default directory when in shell-mode. The first, default method is shell-dirtrack-mode. This mode keeps track of commands such as ‘cd’ that change the working directory of the prompt. This, however, runs into problems with commands it doesn’t recognize, for example because you aliased a command to move to a popular directory.

The other mode is dirtrack-mode, which changes the default directory of the shell buffer based on the prompt. This does require you to have the working directory in your prompt, but a) I like having it and b) if you really want, you can strip it out using hooks.

Dir track-mode is built into GNU Emacs, so you don’t have to download anything special. You do have to customize a regexp to conform to the prompt you want(or change your prompt to conform to the regex). For me, my shell prompts are of the form: username@hostname:path/to/file$ , so I ended up with the following value:

(setq-default dirtrack-list '("^[^@]*@\\([^:]*:[^$].*\\)\\$" 1))

The group used to determine the path, in this case, is hostname:path/to/file. This allows me to have dirtrack-mode work when I ssh into other computers, as long as I configure their prompt to follow this format. This does require me to have the machine I consider ‘local’ to have a ‘hostname’ of ‘/’, but in the following section I’ll show how to get this to work correctly no matter what computer you are using. It took me a long time to figure out how to get tab-complition work in shell-mode when I was sshe’d into another computer. To set your prompt to this value, put the following line in your .bashrc:

export PS1="username@hostname:\w$ "

I like to have my shell buffers contain the directory name in them, so I use the following hook. This causes the shell buffer’s name to change whenever dirtrack changes. It ended up being fairly complicated, as I wanted to be able to have more than one shell buffer open in the same directory without things breaking:

(add-hook 'dirtrack-directory-change-hook
          (lambda ()
            (let ((base-buffer-name (concat "shell-" default-directory "-shell"))
                  (i 1)
                  (full-buffer-name base-buffer-name))
              (while (get-buffer full-buffer-name)
                (setq i (1+ i))
                (setq full-buffer-name (concat base-buffer-name "<" (number-to-string i) ">")))
              (rename-buffer full-buffer-name))))

We have only two things left to do: turn on dirtrack mode, and set the prompt to contain ‘/’ instead of the hostname on the local comuter. The following advice first turns off shell-dirtrack-mode, changes the prompt, and then turns on dirtrack mode. You want to do things in this order, because otherwise dirtrack-mode will try and use the actual ‘localhost’ value, which may confuse tramp.

(add-hook 'shell-mode-hook
          (lambda ()
            (shell-dirtrack-mode -1)
            (insert "export PS1=\"nflath@/:\\w$ \"")
            (comint-send-input)
            (dirtrack-mode 1)
            ))

Whenever a shell buffer is opened, shell-dirtrack-mode is turned off. Then, we send the command that will change the prompt and execute it, and then finally turn on dirtrack mode.

Web Browsing in Emacs

Wednesday, September 2nd, 2009

About a week ago, I was using emacs on a remote computer with only a terminal. I was doing some java coding, and attempted to use java-describe to pull up some javadoc. Of course, since I usually use Firefox for url-browsing, this failed. This prompted me to re-install emacs-w3m, to be used in situations where Firefox was unavailable. I tried emacs-w3m for generalized browsing a while ago, but found it insufficient; it’s a bit slow(although faster than w3), doesn’t support javascript, and is a log uglier. However, it’s better than nothing. You do need w3m to use emacs-w3m; it’s faster than w3 mainly because it is the w3m process that does most of the work.

Installing emacs-w3m is pretty easy: I followed the instructions here to check out the sources from CVS and added them to my load-path. This, as well as the customizations in this blog, were enough to get it set up. As a note: all of the customizations here came from this emacs-wiki page or a page it links to; you may want to see if there is anything else that you’d like on those pages. If you don’t already have the w3m browser, you’ll need to install it. On Ubuntu, you can just do ’sudo apt-get install w3m’.

(setq w3m-session-file "~/.emacs.d/.w3m-session")
(setq w3m-session-autosave t)
(setq w3m-session-load-last-sessions t)
(setq w3m-use-cookies t)
(setq browse-url-browser-function 'w3m-browse-url)
(setq browse-url-new-window-flag t)nn

These are all the variables used for customizing w3m that I used. The first three auto-save my w3m sessions; if I close emacs while having w3m buffers opened, the next time I open emacs on that computer the buffers should re-open, much like how save-visisted-files opens all the files that were opened previously. I also allow w3m to use cookies so I can log into sites like gmail and facebook if I end up wanting to do that.

(require 'w3m)
(require 'w3m-session)
(require 'w3m-cookie)

These are the three w3m libraries that I require. w3m is just for standard browing functionality, w3m-session is for the session-saving mentioned above, and w3m-cookie allows cookies to be used when browsing. There are a lot more w3m libraries you can check out, but for the minimal usage I am planning on using it for this is quite enough.

(defun my-w3m-rename-buffer (url)
  "Renames the current buffer to be the current URL"
  (rename-buffer url t))
(add-hook 'w3m-display-hook 'my-w3m-rename-buffer)
 
(add-hook 'w3m-display-hook
          (lambda (url)
            (let ((buffer-read-only nil))
              (delete-trailing-whitespace))))

my-w3m-rename-buffer will rename the current buffer to that of it’s url. Since w3m by default uses names like ‘*w3m*’, ‘*w3m<2>*, and so on for buffer names, this is incredibly useful. Adding the function to w3m-display-hook forces all w3m buffers to have their URLs as their name. The second hook deletes trailing whitespace from w3m buffers. In a lot of cases, trailing whitespace is added, which makes it harder to navigate to where you expect when using C-e; this removes all of that.

(defun w3m-browse-current-buffer ()
  "Look at the current buffer as rendered by w3m."
  (interactive)
  (let ((filename (concat (make-temp-file "w3m-") ".html")))
    (unwind-protect
        (progn
          (write-region (point-min) (point-max) filename)
          (w3m-find-file filename))
      (delete-file filename))))

In case I have a HTML file open in a buffer I’m editing that I want to view in w3m, I have this function. It will open up a new w3m buffer viewing the current buffer. I haven’t had occasion to use it yet, but I saw it on emacs-wiki and it seemed like something that would eventually be useful.

(unless window-system
  (setq browse-url-browser-function 'w3m-browse-url)
  (setq browse-url-new-window-flag t))

This is what sets Emacs to use w3m instead of Firefox. I only evaluate it when window-system is nil; if it is ‘x’, or anything else, I know I have a graphical display and can thus use Firefox. I change the function to use when browsing urls to w3m-browse-url, which will open the url up in w3m. The other option forces w3m to create a new buffer whenever a URL is browsed, instead of using old buffers.

Emacs - Timing and Upgrades

Monday, August 31st, 2009

I have made a number of upgrades to functions and customizations I’ve previously blogged about, so this post is going to be an aggregation of these improvements. Think of it as a ‘corrections’ post.

In a previous post, I talked about updating imenu-generic-expression for java to work with functions with generic types or annotated arguments. The regular expression there is somewhat inadequate: if you used horrible spacing conventions, it could thing an if statement was a function. This new hook for java-mode to set imenu-generic-expression fixes this case by actually breaking out the annotations, types, and variable names, without just mixing them together as in the previous version.

(add-hook 'java-mode-hook
          '(lambda ()
             (setq imenu-generic-expression
                   `((nil
                      ,(concat
                        "[" c-alpha "_][\]\[." c-alnum "_<> ]+[ \t\n\r]+" ; type spec
                        "\\([" c-alpha "_][" c-alnum "_]+\\)" ; method name
                        "[ \t\n\r]*"
                        ;; An argument list htat is either empty or contains any number
                        ;; of arguments.  An argument is any number of annotations
                        ;; followed by a type spec followed by a word.  A word is an
                        ;; identifier.  A type spec is an identifier, possibly followed
                        ;; by < typespec > possibly followed by [].
                        (concat "("
                                "\\("
                                "[ \t\n\r]*"
                                "\\("
                                "@"
                                "[" c-alpha "_]"
                                "[" c-alnum "._]""*"
                                "[ \t\n\r]+"
                                "\\)*"
                                "\\("
                                "[" c-alpha "_]"
                                "[\]\[" c-alnum "_.]*"
                                "\\("
                                "<"
                                "[ \t\n\r]*"
                                "[\]\[.," c-alnum "_<> \t\n\r]*"
                                ">"
                                "\\)?"
                                "\\(\\[\\]\\)?"
                                "[ \t\n\r]+"
                                "\\)"
                                "[" c-alpha "_]"
                                "[" c-alnum "_]*"
                                "[ \t\n\r,]*"
                                "\\)*"
                                ")"
                                "[ \t\n\r]*"
                                "{"
                                )) 1)))
             ))

The following are a few utilities I wrote in order to write functions such as my-grep. my-fn will take a function with one argument and a prompt, and execute that function with a default of the current word. Defun-my is a macro that defines both the original function and an interactive ‘my’ version of the function. The new my-grep has the same effect as the old my-grep, but uses my-fn.

(defun my-fn (fn prompt)
  "When given a function taking one argument and applying a function to it, will use that function
   and default to the word at point, with a prompt including that word."
  (let ((default (current-word)))
    (let ((needle (read-string (concat prompt " <" default ">: "))))
      (if (equal needle "")
          (funcall fn default)
        (funcall fn needle)))))
 
(defmacro defun-my (name prompt &rest body)
  "Will define both a function and a my- version of the function,
which defaults to the word at point."
  `(progn
     (defun ,name (arg) ,@body)
     (defun ,(intern (concat "my-" (symbol-name name))) ()
       (interactive)
       (my-fn (quote ,name) ,prompt))))
 
(defun my-grep nil
  "Grep the whole directory for something defaults to term at cursor position"
  (interactive)
  (my-fn (lambda (arg) (grep (concat "egrep -s -i -n -r " arg " * " ))) "grep for"))

I also used defun-my in order to upgrade java-describe. The new ‘my-java-descibe-class’ does the same thing, except it defaults to the word at point. I also renamed it to java-describe-class, since I’ve been working on some other Java utilities and wanted to make this name more specific.

(defun-my java-describe-class "Open Javadoc for Class"
  "Loads javadoc for specified class in your browser."
  (interactive "MClass Name: ")
  (let ((my-string (replace-regexp-in-string
                    "^.*class-use/.*\n"
                   ""
                   (shell-command-to-string
                    (concat "find ~/.emacs.d/documentation/java/ -name "
                            arg
                            ".html"))
                   )))
    (string-match "^\\(.*\\)$" my-string)
    (browse-url (match-string 0 my-string))))
 
(global-set-key (kbd "C-x j c") 'my-java-describe-class)

I also upgraded my-help, a function that gives documentation on whatever the point is on. It now checks to see if the buffer is a java buffer; if so, we open the javadoc for the current word instead of calling man on it. I was going to switch the order of checking whether a function or symbol was described first, in the case where a function and variable have the same name, but the issue then is that since function-called-at-point will return the calling function if you are anywhere in a function call, it would frequently mask variable lookup.

(defun my-help ()
  "If function given tries to `describe-function' if variable
uses 'describe-variable', otherwise uses `manual-entry' to display
manpage of a `current-word'."
  (interactive)
  (let ((var (variable-at-point))
        (fn (function-called-at-point)))
    (if (symbolp var)
        (describe-variable var)
      (if fn
          (describe-function fn)
        (if (eq major-mode 'java-mode)
            (java-describe (current-word))
          (man (current-word)))))))

I previously just added visual-line-mode to text-mode-hook, which actually toggled visual-line-mode in the buffer and could lead to strange behaviour. This correction turns visual-line-mode on when entering text modes.

(add-hook 'text-mode-hook '(lambda nil (visual-line-mode 1)))

A reader suggested this improvement in the comments of this post. This will open the current file as sudo at the current position; the old function would lose the position you were at.

(defun sudo-edit-current-file ()
  (interactive)
  (let ((pos (point)))
    (find-alternate-file (concat "/sudo:root@localhost:" (buffer-file-name (current-buffer))))
    (goto-char pos)))

Yank-pop is an advice I describe here to properly indent code fragments. I implemented a suggestion I received in the comments of the linked post in order to make it work better when transient-mark-mode is enabled.

(defadvice yank-pop (after indent-region activate)
  (if (member major-mode
              '(emacs-lisp-mode scheme-mode lisp-mode
                                c-mode c++-mode objc-mode
                                latex-mode plain-tex-mode))
      (let ((mark-even-if-inactive transient-mark-mode))
        (indent-region (region-beginning) (region-end) nil))))

I created a few new functions to keep track of how long each of my customization files take to load. While load time isn’t a problem for me right now, and I could easily fix it if it was by byte-compiling my customizations(right now, the only compiled elisp file I have that is not part of GNU Emacs core is js2.el), I do want to be able to account for what is taking the most time to load. While emacs-init-time tells me how long emacs took to initialize in total, I want a more fine-grained solution. I implemented this by defining time-load-file, a function that would load a file and return a pair consisting of the filename and the time taken to load it in seconds, and changing load-directory to use time-load-file instead of load-file. By saving the results of load-directory, I have a permanent record of the time taken to load each file.

(defun time-load-file (file)
  "Loads a file and returns a pair consisting of the filename and
the time in seconds it took to load."
  (let ((prev-time (float-time)))
    (load-file file)
    (cons file (- (float-time) prev-time))))
 
(defun load-directory (dir)
  "Loads every .el file in a directory."
  (mapcar 'time-load-file (directory-files dir t "\\.el\\'")))
 
(setq customizations-directory-load-times (load-directory "~/.emacs.d/customizations/"))
(setq util-directory-load-times (load-directory "~/.emacs.d/utilities/"))

That’s all I have for now, but I will no doubt improve my customizations further, so once I amass a suitable number I’ll do another one of these posts. If you see anything that should be corrected or could be improved in any of my posts, please leave a comment.

Easier Emacs

Friday, August 28th, 2009

I have enough random emacs customizations to put up another post, so here they are. Emacs is a great text editor, but a lot of the functionality that I have discovered is not enabled by default or not existing, but it is fortunately incredibly customizable so I can add it myself, or find someone else and use their customizations. A lot of these were taken from the Emacs Starter Kit - I browsed through their codebase and used the pieces that looked interesting.

(global-set-key (kbd "C-c r") 'revert-buffer)
(global-set-key (kbd "C-c a") 'apropos)
(global-set-key (kbd "C-c v") 'visual-line-mode)
(define-key isearch-mode-map (kbd "C-o")
  (lambda () (interactive)
    (let ((case-fold-search isearch-case-fold-search))
      (occur (if isearch-regexp isearch-string (regexp-quote isearch-string))))))

These are some keybindings for commands I use pretty frequently, as well as an additional command for isearch-mode. Revert-buffer does just as advertised; it re-loads the current buffer from what is saved on disk. Apropos, a very powerful help command, will search all defined symbols for the pattern you specify. Visual-line-mode is the Emacs23 version of longlines-mode, except much faster; it will make lines wrap and not extend past the window. I often change whether I want to be in this mode or not, so I made C-c v toggle this mode. The last keybinding makes C-o call occur with the string you are searching for when you are performing an interactive search.

(setq-default tab-width 4)
(setq comment-auto-fill-only-comments t)
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)

These are just some standard Emacs customizations. I set the tab-width to be 4 in all buffers and have auto-fill only work with comments in programming modes. The next two lines just enable two disabled commands that I sometimes use; It gets annoying to specify that I want to do these each time.

(defun uwb ()
  "Untabifies the whole buffer"
  (interactive)
  (untabify (point-min) (point-max)))
 
(defun twb ()
  "Tabifies the whole buffer"
  (interactive)
  (tabify (point-min) (point-max)))
 
(defun eval-and-replace ()
  "Replace the preceding sexp with its value."
  (interactive)
  (backward-kill-sexp)
  (condition-case nil
      (prin1 (eval (read (current-kill 0)))
             (current-buffer))
    (error (message "Invalid expression")
           (insert (current-kill 0)))))
(global-set-key (kbd "C-c e") 'eval-and-replace)
 
(defun shell-current-directory ( )
  "Opens a shell in the current directory"
  (interactive)
  (shell (concat "shell-" default-directory "-shell" )))
(global-set-key (kbd "C-c s") 'shell-current-directory)

uwb stands for Untabify whole buffer, and is used when I have a programming file that I quickly need to standardize to keep from hooking messed up. Since it isn’t something I have to do often, I don’t need a keybinding for it. Similarly, twb tabifies the entire buffer. Eval-and-replace is similar to eval-last-sexp, a function I use quite frequently, except it replaces the evaluated expression with the result. This is something that will be useful to me; often I ended up doing this task manually, so it gets it’s own keybinding. The last command is one I now use pretty much constantly. shell-current-directory just creates a shell in the directory that the current buffer is in.This allows you to quickly pop into a shell without having to navigate to that directory, or do an eval-expression yourself. The one thing that I may end up modifying this to do is have the buffer name change based on the directory of the shell, since sometimes I wander off in the shell I opened and then the name is not that of the current directory.

(add-hook 'find-file-hook
         (lambda ()
           (if (string-match "log" (buffer-name (current-buffer)))
               (visual-line-mode -1))))

At work, I often deal with large logfiles with long lines, and I usually want to quickly scan through them. Not having visual-line-mode on in this case is very helpful, since I can just scan through the log type with one per column and see if there is an error. There’s a couple of other modifications I’ve been thinking of writing and packaging up as a log-file-mode, since I haven’t been able to find one of my own, but I have not gotten around to this yet.

The next set of modifications isn’t actually useful; they remove functionality from emacs instead of increasing it. I noticed I use the arrow keys more than I should, and want to train myself to use C-n and the like and not leave the home row as often. To this end, I disabled the arrow keys.

(global-unset-key (kbd "<left>") )
(global-unset-key (kbd "<right>") )
(global-unset-key (kbd "<up>") )
(global-unset-key (kbd "<down>") )
 
(global-unset-key (kbd "C-<left>") )
(global-unset-key (kbd "C-<right>") )
(global-unset-key (kbd "C-<up>") )
(global-unset-key (kbd "C-<down>") )
 
(global-unset-key (kbd "M-<left>") )
(global-unset-key (kbd "M-<right>") )
(global-unset-key (kbd "M-<up>") )
(global-unset-key (kbd "M-<down>") )

That’s it for now - let me know if there are any good packages for viewing log files, and if you have any suggestions for additional customizations please leave them in the comments.