Thursday, September 27, 2007

11 Visual Studio tricks in Emacs

Recently I read the blog post "11 Visual Studio 2005 IDE Tips and Tricks to Make You a More Productive Developer" which has some neat tips indeed. I thought I would investigate which of the tips can be replicated in emacs, which are easier or more powerful in emacs and vice versa.

I've been using Visual Studio for over 10 years though I'm certainly not a power user, and recently I only use it for building and occasional code editing. I do more editing in emacs. I'm not writing this post to prove that one is better than the other, it is more for the learning experience for myself, and hopefully somebody will find something interesting here.

(1) Express Yourself with Regular Expressions

The example is to convert

, last_name
, ssn
, employee_id

into

+ "last_name"
+ "ssn"
+ "employee_id"

using a regex. Well, I'd probably record a keyboard macro to do that, but let's do the regex replace instead.

The syntax of the regex is a little different in emacs, but the basic sequence looks like this:

Alt-x replace-regexp
\(, \)\(.*$\)
, "\2"

Notice you need slashes for the brackets to make the groups.

Verdict: Visual Studio lets you use Regex's in script, and emacs lets you do it in elisp code... and they both have the functionality needed for the tip. Draw.

(2) Take (Keyboard) Shortcuts

This tip is to simply use keyboard shortcuts. Well in fact you won't get anywhere with emacs without using them. So this is kind of a mute point.

But I'll list some random keyboard short cuts for completeness...

Alt z runs zap-to-char, kills everything up until the character you enter.

Alt . runs find-tag. Finds the next occurence of current tag in the tags table, for finding function and variable declarations for example.

Ctrl U Alt . finds previous tag

Ctrl < goes to the start of a buffer

Ctrl > goes to the end

Ctrl H m describes the current mode, which is handy if you just downloaded a new editing mode and you want to see what the keys are and so on

Alt t runs transpose. You can flip two words around.

Verdict: Another draw.

(3) Make New Shortcuts

This is straight forward in emacs...

(global-set-key [M-f2] 'zap-to-char)

... sets Alt-F2 to do zap-to-char

You can override keys globally like that, or you can do local-set-key to change that key only for the current editing mode.

Verdict: emacs and Visual Studio both allow remapping anything they can do to a key, and they both allow you to redefine a key differently for different modes. Another draw!

(4) Use Code Snippets

I wasn't aware of this feature for Visual Studio so I checked it out briefly. So it lets you dump out text, such as automatically creating empty for loops or adding set and get fields given a field name.

Well in emacs there are abbreviations. So for example let's say I want for( to automatically expand to for(int i; ithen I can make an abreviation, by going into the mode I want this to be active, and typing

Alt-x abbrev-mode (turn the mode on)
Alt-X define-mode-abbrev (interactively add a new abbreviation for this mode)
for
for(int i; i
and now when I type for and space, it will expand automatically.

If you don't want it to expand then you type Ctrl-Q before you complete the abbreviation.

But snippets let you do more advanced stuff like take a field name and create the get, set fields. Well I would write elisp code for that kind of thing, or again use a keyboard macro.

Abbreviations are nice and easy to use, but they don't have the power of snippets.

Verdict: Visual Studio code snippets don't seem to map directly to emacs. In emacs you can use the more basic abbreviations, or roll your own solution for wrapping text in more dynamic ways.

(5) State Your Preferences

Not a lot to say here. emacs is fully configurable through the startup file .emacs, so you can do configure everything as you want it to be.

Verdict: Draw.

(6) "Attach to Process" to Start Debugging ASP.NET

Emacs doesn't support windows debugging, of course, but you can use gdb to debug processes. So the same functionality would be :

Alt-x gdb
attach [process ID]

Verdict: Draw.

7) Stop Conditionally (Conditional Breakpoints)

Again, this is a windows only thing... you can run gdb and type

break [LOCATION]

and

condition [COND]

to set up a conditional breakpoint.

Verdict: Draw. You can't debug windows processes from emacs, and you can't debug linux processes from Windows, but both offer debugging from within the IDE.

(8) Employ Task List Tokens

This is an odd feature. By typing // TODO in C++ code, for example, you can view the TODO's in a task list window for that file.

Emacs lets you do this with say the 'occur' function.

Alt-X occur
TODO

Will give a list of lines containing TODO.

You could make an elisp function to wrap this up into a task list function:

(defun task-list()
(interactive)
(occur "TODO"))

Verdict: Not much of a feature really, but yeah, another draw.

(9) Go Directly to Any File with the Find Combo Box

I couldn't get this tip to work, but Alt-Shift O seems to be the one he is talking about. A very nice list of files, and you can quickly open a file by typing part of the filename.

emacs doesn't include the files in your current project, so we don't have a direct comparison, but let's assume you have a root directory containing your source and you want to find files matching a regex:

Alt-x find-dired
d:\YourSourceFiles\
-regex ".*SEARCHTEXT.*"

This will open a dired window (like a file manager dialog box but lets you do lots more things to the files) containing the matching files.

Verdict: emacs is a bit better than studio in that you can search using all the power of the unix find command, but it's more fiddly to use, and there's no equivalent to Studio managing all the files in each project. (That I know of).

(10) Type Ahead (Incremental Search) in Lists

So for example in Studio, do Ctrl-O and you get a file dialog. Typing letters gradually filters the available files until you get the one you want.

Emacs has exactly the same thing.

Ctrl-X Ctrl-F to visit a file for example (although this works with anything that asks you for a file.)

Firstly you can use the buffer history to find files you opened and closed earlier, and also you can edit this, so if you just opened a .cpp file, you can change it to .h and load that easily.

Secondly hitting tab will cycle through possible files based on what you typed so far, but also open a buffer with the current valid files, so you can switch and select from there.

Finally, if you open the wrong file by mistake you can run 'find-alternate-file' and load a different file into the buffer you opened.

Verdict: emacs wins by a nose. More flexibility.

(11) Automate with Macros and Visual Studio Automation

emacs also has very cool macro recording...

Ctrl-X ( starts recording

do your thing

Ctrl-X ) ends recording

Ctrl-X e runs the macro

If you make a useful macro that runs on one line, you can then run it multiple times:

Ctrl-U 10 Ctrl-X e

runs the macro 10 times for example.

You can also edit the macro with edit-last-kbd-macro, which brings up an editor.

Well that's it, I'm sure I've missed out a lot of emacs features, I've been using it for about 4 years and I know there is still a lot of stuff in there I haven't discovered!

Saturday, September 22, 2007

Word numbers programming puzzle

Reading Reddit last week I came across an interesting programming puzzle.

http://www.itasoftware.com/careers/puzzles07.html

I've written a straightforward Common Lisp solution which is pasted below. What is interesting about this problem, and what would make it a good interview question, is that coding up the basic solution as I have here only poses more problems.

None of the Lisp environments I've tried have enough heap space to complete this problem, even though in terms of time complexity it is O(n). Judging by how long it takes to run on a few hundred thousand numbers, and then several million, it would take about 20 hours on my 2Ghz PC to solve for 1 billion numbers.

Even if I used the file system to hold the numbers, assuming each number fits in 50 chars of text, 4 bytes for the value and a further 4 to hold the length of the string, that is still in the order of 50Gb. You would then need to sort that file a bit at a time in memory, using a merge sort, and finally do a linear run through the file until you get the 51,000,000,000nth number.

Some clever folk have presented a more intelligent solution here...

http://conway.rutgers.edu/~ccshan/wiki/blog/posts/WordNumbers1/

Here is my solution so far:


#|
Word Numbers

This is a partial solution to the problem found at http://www.itasoftware.com/careers/puzzles07.html
by Justin Heyes-Jones

I say partial because it does actually work, and if you had a lisp environment with enough memory, it would finish
in about a day. But the real solution seems to be either to spot patterns so you don't have to generate and sort
all 1 billion numbers, or to use the file system to cope with what your computer memory cannot.

"If the integers from 1 to 999,999,999 are written as words, sorted alphabetically, and concatenated, what is the 51 billionth letter?"

To be precise: if the integers from 1 to 999,999,999 are expressed in words
(omitting spaces, 'and', and punctuation[1]), and sorted alphabetically so that the first six integers are

* eight
* eighteen
* eighteenmillion
* eighteenmillioneight
* eighteenmillioneighteen
* eighteenmillioneighteenthousand

and the last is

* twothousandtwohundredtwo

then reading top to bottom, left to right, the 28th letter completes the spelling of the integer "eighteenmillion".

The 51 billionth letter also completes the spelling of an integer. Which one, and what is the sum of all the integers to that point?

[1] For example, 911,610,034 is written "ninehundredelevenmillionsixhundredtenthousandthirtyfour"; 500,000,000 is written "fivehundredmillion"; 1,709 is written "onethousandsevenhundrednine".

|#

; (load (compile-file "wordnumbers.lisp"))
; (solve 999999999 51000000000) ; unlikely to finish unless you have a massive memory heap
; (solve 10 26) ; will work, but may not get you the job ;-)

;;;; Utilities

(defmacro with-string-words((str word) &body body)
"Utility macro to iterate over a string and return each word (anything between spaces)"
`(do* ((start 0 (if end (1+ end) nil))
(end
(position #\Space ,str :start 0)
(if end (position #\Space ,str :start (1+ end)) nil))
(,word (subseq ,str start end) (if start (subseq ,str start end) nil)))
((null start))
,@body))

;;;; Numbers are stores as the number in words, the length of this string and finally the numeric value

(defun get-words(lst)
(first lst))

(defun get-length(lst)
(second lst))

(defun get-value(lst)
(third lst))

(defun remove-and(str)
"remove occurences of 'and' from a string"
(let ((new-str (make-array 0 :element-type 'character :fill-pointer 0 :adjustable t)))
(with-string-words (str word)
(if (string/= "and" word)
(and
(setf new-str (concatenate 'string new-str word))
(setf new-str (concatenate 'string new-str " ")))))
new-str))

(defun char-space-or-hyphen-p(c)
(if (or (char= #\Space c) (char= #\- c))
t
nil))

(defun remove-spaces-and-hyphens(str)
"remove spaces and hyphens from a string"
(remove-if #'char-space-or-hyphen-p str))

(defun get-number-as-words(n)
"Use common lisps built in English text number output"
(format nil "~r" n))

(defun get-numbers-as-word-list(n)
"get the numbers from 1 to n and return as a list of strings and the lengths"
"of each string as a list of three items, words, length of word string and"
"actual numeric value"
(loop for n from 1 to n collect
(let* ((str (get-number-as-words n)) (len (length str)))
(list (convert-text str) len n))))

(defun compare-word-and-len(a b)
"given a string, length pair compare on alphabetical order"
(string< (get-words a) (get-words b)))

(defun sort-number-word-list-alphabetically(lst)
(sort lst #'compare-word-and-len))

(defun convert-text(str)
(remove-spaces-and-hyphens (remove-and str)))

(defun get-number-from-letter-index(lst target-index)
(do
((number 0 (1+ number))
(index 0 (+ index (get-length (nth number lst)))))
((> number (1- (length lst))))
(if (<= target-index (+ index (get-length (nth number lst))))
(return-from get-number-from-letter-index number)))
nil)

(defun sum-to-n(lst n)
(if (>= n 0)
(+ (get-value (car lst))
(sum-to-n (cdr lst) (1- n)))
0))

(defun solve(num n)
"Solve the problem for 'num' numbers, finding character position n"
(let ((lst
(sort-number-word-list-alphabetically
(get-numbers-as-word-list num))))
(format t "Made list~%")
(let ((number
(get-number-from-letter-index lst n)))
(format t "Found number~%")
(let ((value (get-value (nth number lst))))
(format t "Done.~%Number at character pos ~a is ~a. Sum to that number is ~a~%" n value (sum-to-n lst number))))))


Wednesday, September 12, 2007

Commenting out a block of C++ in emacs

Here are couple more simple functions, used for commenting out a block of C++ code.

c++-comment-line
below simple inserts "//" at the start of a line

c++-comment region will take the current region and run the c++comment-line on each line.


(defun c++-comment-region()
"Comment a region out"
(interactive)
(save-excursion
(save-restriction
(narrow-to-region (point) (mark))
(goto-char (point-min))
(while (> (point-max) (point))
(c++-comment-line)
(forward-line)))))

(defun c++-comment-line()
"Comment a line of C++ out"
(beginning-of-line)
(insert "//"))

Tuesday, September 11, 2007

Adding C++ class names to a function name

I use this elisp code to add a C++ class name to a line such as:

void getNameRawString(char *string);

automatically becomes ...

void SomeClassName::getNameRawString(char *string);


This is useful as you can copy a bunch of class method definitions from a header file you've just created and then run this on each line to add the class names.

First I wrote a utility function that finds the function name, which is presumed to be letters and underscores, following space and ended with a bracket. The function name includes the word probably because it might not work depending on your formatting, but you can twiddle the regex to get what you want.

So as you can see this finds the match for the regex, which will place the point at the end of the search. Then I search backwards for a space which puts the point where we want to insert the class name and double colons...


(defun find-function-start-probably()
(interactive)
(re-search-forward " [*&_a-zA-Z]+(")
(re-search-backward " ")
(forward-char)
(if (or
(char-equal (char-after) ?*)
(char-equal (char-after) ?&))
(forward-char)))


Finally the function below calls find-function-start-probably. It prompts for the class name, finds the function and inserts the text. The program automatically aborts if there is no match. You can override that behavior by passing arguments to re-search-forward.


(defun classname-add(classname)
(interactive "sEnter class name: ")
(find-function-start-probably)
(insert classname)
(insert "::")
(beginning-of-line)
(forward-line))


Improvements on the way:

Multi-line version: do this over multiple lines

Improvements unlikely but would be nice:

Parse the header file more intelligently and create all the class function definitions with empty function bodies in a specified buffer

Friday, September 7, 2007

Fixing up windows pathnames to use in cygwin

I use emacs within Cygwin, and often I want to paste a pathname from an explorer window into emacs and use it there. Unfortunately you have to edit it by hand before it will work.

So for example a path like:

c:\code\haskell\cats\monkeys

Needs to be converted to:

/cygdrive/c/code/haskell/cats/monkeys

The following interactive elisp function does that with the currently selected text:



(defun win32-to-cygwin-path()
"Converts a win32 path into a cygwin happy one"
(interactive)
(save-excursion
(save-restriction
(narrow-to-region (point) (mark))
(goto-char (point-min))
(insert "/cygdrive/")
(goto-char (point-min))
(while (search-forward ":" nil t)
(replace-match "" nil t))
(while (search-forward "\\" nil t)
(replace-match "/" nil t)))))


Nothing much clever going on here, just two search and replaces for the slashes and to removed the colon, and I insert the cygdrive prefix.