-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 =pod So this week I've been learning Emacs Lisp extensively. I've tried to learn it a few times, but I've always gotten sidetracked by programming in a language I actually know. This time I was really convinced that I needed to use emacs to solve my problem (interactively editing text files), so I pushed through it and figured it all out. C along with the included manual in C made this generally enjoyable. I'm no wizard, but I finally know how to do things like write modes and C rules (along with basic lisp operations, like macros). Anyway, tonight while working on C, I was sitting at the bottom of a file, in the middle of a statment like C<< my $foo = Some::Module-> >> when I realized I needed to C at the top of the file. That's always painful, because I have to set the mark, move to the top of the file where the use statements are, add the use statement, exchange-point-and-mark, and then try to remember what I was doing before my flow was broken. This takes at least 10 seconds and stresses me out, so I decided to automate it: lang:Common Lisp (defun add-use (module) "Add a perl use statement after the existing use statements" (interactive "sUse statement: use ") (save-excursion (goto-char (point-max)) (condition-case nil (re-search-backward "^\\(use .+;\\|#!/\\)") (error (goto-char 0))) (end-of-line) (insert (concat "\nuse " module)))) I C this to C in cperl-mode-hooks. Now when I want to use a module, I just invoke this function, it prompts me (in the minibuffer) for everything after C, and then inserts it for me (preserving the point and mark, so the text just "appears" at the top of the file). The algorithm I use to determine where the statement goes is, look for the last C line, the shebang line, or, failing those, the beginning of the file, then insert the new use statement after that. This seems to be good enough; I might add something to sort the use statements since I tend to do that manually. Anyway, I guess I'm happy that I can fluently extend my editor now; this excersise only took me one trip to the manual (for C). Learning elisp was time well spent. =head2 UPDATED L suggested using C to get the name of the module near the point and use that as the default. Accordingly, I've updated the code to look like this: (require 'thingatpt) (defun bounds-of-module-at-point () "Determine where a module name starts for (thing-at-point 'perl-module)" (save-excursion (skip-chars-backward "[:alpha:]:\\->") ; skip to F in Foo::Bar-> (if (looking-at "[[:alpha:]:]+") ; then get Foo::Bar (cons (point) (match-end 0)) nil))) ; allow (thing-at-point 'perl-module) (put 'perl-module 'bounds-of-thing-at-point 'bounds-of-module-at-point) (defun read-with-default (string &optional default error) (let ((read (read-string (if default (format "%s (default %s): " string default) (format "%s: " string))))) (if (equal read "") (setq read nil)) (if (and (not read) (not default)) (error error)) (if (not read) (setq read default)) read)) (defun add-semicolon (string) (if (string-match ";" string) string (concat string ";"))) (defun add-use () "Add a new perl use statement after the existing use statements." (interactive) (let ((module (read-with-default "Module" (thing-at-point 'perl-module) "You must specify a module to use!"))) (save-excursion (goto-char (point-max)) (condition-case nil (re-search-backward "^\\(use .+;\\)") (error (goto-char 0))) (end-of-line) (insert (concat "\nuse " (add-semicolon module)))))) Not quite as elegant, but more featureful. When the point is near a module-name, executing C results in a prompt like: lang:undef Module (default Foo::Bar): You can just press enter, and it will add C to your program. I sugared up the interface in other ways; if you forget the trailing semicolon, it will be added for you. The C is pretty smart about finding the nearby module; if you type C<< Foo::Bar-> >> it will know the module's C. Finally, you get a nice error message if you don't type anything. Thanks again, Joshua. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFHW6hB2rw+dVvzZm0RAngxAJ4sLbXmVAhFQJmBtGZt+I7f4VyV2wCgg1oe Aplhc4MpCacwKenMLCt9L6E= =f3bG -----END PGP SIGNATURE-----