October 27, 2002
Bulk file renames

I wanted to rename all of the files in a directory that ended in .txt so that they ended in .xml . Clearly some sort of script was needed, but what language to use? I chose elisp, because I was working in emacs and the interactive help made it easy to find the functions I wanted. Thinking about it later I wondered how I'd do this in other languages so here also are python and perl versions with the same functionality. None are heavily tested but all work if run in the directory containing the files to rename. My final impression? The elisp one was the quickest to write and I think is the easiest to manage for this job.

In elisp:

(defun rename-some-files (dir)
  "Rename some files."
  (interactive "DDirectory name ")
  (mapc (lambda (f) (rename-file (concat f ".txt") 
				 (concat f ".xml")))
	(mapcar 'file-name-sans-extension
		(directory-files dir nil "\.txt$")))

In python:

import os
import re

pat = re.compile('\.txt$')
map(lambda f: os.rename(f + '.txt', f + '.xml'),
    [os.path.splitext(f)[0] for f in os.listdir(os.getcwd()) \
     if pat.search(f)])

In perl:

use Cwd;
use File::Basename;

opendir(DIR, cwd());
map(rename($_ . '.txt', $_ . '.xml'),
    map(basename($_, '.txt'),
	grep(/\.txt$/, readdir(DIR))));
closedir(DIR);
Posted by Alex. Permalink
Comments
Python's os.path.walk() is a nice little util, if you wanted a recursive version of you code. I believe it also does some sort of directory caching, but it's been a while since I've used Python. I believe it would have been more maintainable Python to split the map into two lines. Because Python is not a functional language, and the indentation thre doesn't really help you. Posted by: Tj on October 28, 2002 03:57 AM
BTW, how do you insert newlines into these comments? Hitting enter doesn't do it, and html is stripped. Posted by: Tj on October 28, 2002 03:59 AM
os.path.walk() isn't nice - it's horrid! See http://groups.google.com/groups?selm=RoLM6.10846%24sk3.2912386%40newsb.telia.net Posted by: Simon on October 28, 2002 07:35 AM
Well, the thing is it's great if you like functional programming styles. So I'm glad that Guido made the "mistake" of including filter/map/reduce/lambda, because I wouldn't have used Python otherwise, and I've learned how to write it so it's clear to anyone. In fact, 70% of my code is some filter or map. But admittedly, os.path.walk's syntax is hard to remember; you just have to cut & paste it. Not hard, I use it all the time, just annoying. Posted by: Tj on October 28, 2002 09:23 AM
Use the shell. If you're on windows, get Cygwin. Then you can just do for i in *.txt; do mv $i ${i%%.txt}.xml; done from the command line. Posted by: JLM on October 29, 2002 09:32 AM
The shell solution's nice. I'm not familiar enough with shell coding to be able to knock this sort of stuff out quickly though. The biggest inhibitor for quick and dirty scripts is "how quickly can I write this stuff or find something prewritten". With elisp and the build in help (C-h f function-name) it's quick to find the things you need. You also need, especially with perl, to have a good idea about what all of the functions etc are before you can find them in the manual. Posted by: Alex on October 29, 2002 01:28 PM
Perl's core File::Find module can make this a lot easier. use Cwd; use File::Find; find(sub { /^(.*)(?:\.txt)$/ and rename $_, "$1.xml" }, cwd()) Posted by: Zed on November 29, 2004 03:06 PM
Perl's core File::Find module can make this a lot easier. use Cwd; use File::Find; find(sub { /^(.*)(?:\.txt)$/ and rename $_, "$1.xml" }, cwd()) Posted by: Zed on November 29, 2004 03:07 PM
Actually, I'd misread your intent as doing this recursively through subdirectories under the current directory. For a single directory, File::Find is overkill. perl -e '/^(.*)(?:\.txt)$/ and rename $_, "$1.xml" for ' Posted by: Zed on November 29, 2004 03:41 PM
May 24, 2002
Saving time with Emacs

The best thing about Emacs is the ease with which it can be extended. Here's a simple function that I wrote in a couple of minutes to add <span> tags round the currently selected region. Saved me a lot of boring copy and paste or typing.

(defun ajm-ref (s e)
  "Add <span class=\"ref\"> </span> round the text in the region
 and then call fill-paragraph to reformat."
  (interactive "r")
  (goto-char e)
  (let ((end (point-marker)))
    (goto-char s)
    (insert "<span class=\"ref\">")
    (goto-char end)
    (insert "</span>"))
  (fill-paragraph nil))
Posted by Alex. Permalink
Comments
February 28, 2002
Emacs continues to impress

I've just finished adding incremental search by java method name to the elisp minor mode jxminor that I maintain. When I started I thought it would be nearly impossible to do a decent job but it turned out much better than I could have hoped.

If your an elisp expert you may find what follows rather obvious. If so do you have any suggestions for improvement?

Anyway, the code that provides incremental search is 2074 lines of code and comments. There is no way I was going to be able to reproduce that functionality so I thought at first that my best option would be to patch it somehow. The actual work of searching is done by one function isearch-search and it chooses between word-search-forward/backward, re-search-forward/backward and search-forward/backward depending on various variable settings. If you just press C-s or C-r you'll end up calling search-forward or search-backward. If another pair of functions could be added that would solve the problem.

However, when I looked at the code though I had the thought "if I could just rebind search-forward and search-backward so that my functions got called instead that would solve the problem". This is easy in scheme as there's only one namespace. Looking around I found the function fset that changes the function that a symbol points to. Now the problem is reduced to being able to save the functions search-forward/backward are bound to, rebind them to the method name search functions, execute isearch-search and restore the original bindings.

Turns out this is easy as well. Using the defadvice macro you can arrange for code you write to be "wrapped around" any other function. So the wrapper I wrote does the save, execute and restore described. What's even better is it's easy to turn the wrapper function on and off so you don't have to have a complex one that can deal with being called in all sorts of situations.

The final solution is as simple as having the java incremental search function turn the wrapper on for isearch-search and then call the normal incremental search function. This gives you the full mini buffer editing capability that isearch provides but with a different underlying function to do the actual searching.

I was very impressed, as I always am, with what you can do in emacs and how very easy it is to do it.

Posted by Alex. Permalink
Comments
February 17, 2002
java extras minor mode

This elips stuff is getting out of hand! The original single file with a few functions in it has become four files that define an emacs minor mode to help when editing java code. Available for download here.

I find these quite useful and I spend my work days writing java so I hope they will be useful to others also. Functions are provided for managing import statements, inserting log4j debugging statements, and creating skeleton javadoc comments for methods.

In the future I want to add some sort of template system to make generation of repetitive code easier. The scenario I have in mind goes like this...

I see a piece of code I want to make into a reusable template so I set the emacs region to surround it and call the templatize command. This copies the code to a new buffer in templatize mode. Now, in templatize mode I can select regions of the buffer corresponding to the variables sections I want to make variable when the template is instantiated to create code. I think that there are only two sorts of regions in the basic system, those that get their values by prompting the user, and those whose values are provided by applying some sort of function to an input value. In addition to the standard elisp functions some java specific ones, such as initial-upcase and initial-downcase should be provided as well.

Once the code is marked up it is used to generate a data structure for saving to a file. I'm still debating how to save the data, as a simple structure or as some sort of function definition.

Posted by Alex. Permalink
Comments
February 13, 2002
Further ELISP changes

One of the benefits of using emacs is that as well as using a great tool you get to modify and customize it to make it even better. Just as carpenters can built jigs to make repetitive or difficult table saw cuts quicker or easier emacs users can add bits on to emacs for the same reasons. Besides, hacking on elisp is a great change from writing java code.

With that intro unfortunately the only change I've made recently is to my java stuff package. The import checking function now does a better job of commenting out imports that are duplicates or that are only referenced in commented out code. Here's the code and here's an htmlized version.

Posted by Alex. Permalink
Comments
January 11, 2002
More elisp java-stuff changes

I made yet more changes to my package of elisp functions for helping with java editing in emacs. This set adds a function to insert log4j debugging messages into the code.

The formatting of the inserted code is controlled by the java mode so it should end up looking the same as the stuff you write by hand. You can change logCat to some other value by modifying the value of the java-log4j-statement variable. For example:

if (logCat.isDebugEnabled())
    logCat.debug("a" +
                 b);

Here's the code for downloading and for easy reading in a browser.

Posted by Alex. Permalink
January 02, 2002
Update to elisp code I've made some changes to my elisp code (original item) as a result of using it in anger at work. I found one annoyance, java-sort-imports was modifying the kill ring because I was using kill-region and yank instead of the recommended delete-region. I also got tired (after doing it about three times) of manually deleting import statements after running java-check-imports so I decided to add a funtion java-delete-commented-imports to do that automatically as well. Of course when I sat down to make those changes it all got a bit out of hand and I found myself adding a menu to get to the functions. So, the package now lets you add an Extras submenu to the Java menu in java mode. Here's the modified code for downloading and here it is formatted for easy reading in a browser. As before the formatting is courtesy of the htmlize package.
Posted by Alex. Permalink
Comments
December 21, 2001
Extending emacs for editing java I've written some emacs extensions in the past. I've even written a couple of pretty large, in terms of lines of code, complete modes for editing programs stored in a proprietary file format. The pieces of elisp code linked to here are not that large but automate a couple of functions I like to perform for the Java I write. And what are those functions. The first is to sort the import statements. I find this makes it much easier to see what a program is actually using. You can probably guess that I really don't like import java.foo.*;. In emacs I can use M-x java-sort-imports to order the statements the way I like to see them. The second is to make sure that I'm not importing more classes than I need to. I know it doesn't actually make a difference to the generated bytecode but it makes it difficult to use the import statements to help see the inter class dependencies when looking at the source code. I can use M-x java-check-imports to comment out import statements that import classes that appear not to be referenced in the source code. Obviously it can't check import statements that don't specify the class, i.e. that end in *. Here's the code for downloading and here it is formatted for easy reading in a browser. The formatting was done using the htmlize package, which does a great job.
Posted by Alex. Permalink
Comments
If you take a look at JDEE [http://jdee.sunsite.dk/] you'll see that it provides this functionality and a whole lot more already. Posted by: Ade on February 6, 2002 04:12 AM
I've tried several times to use JDEE. It is very comprehensive, but setup is a bear, and it has always either conflicted with some other thing in my ancient, baroque (14-year-old) .emacs file set. This looks like a nice light alternative. Thanks! Posted by: Bill O'Donnell on December 23, 2004 10:40 AM