If you read Coding Horror or Joel On Software, you already know about stackoverflow.com. In a nutshell, it's a place where you can ask coding questions and receive answers quickly. You can also participate by voting answers up/down and answering questions.
stackoverflow.com works really well, the overall design is very simple, clean, and easy to use.
The emacs community there is pretty small, but questions do come up now and then. In general the answers are fairly good (I think mine are stupendous, feel free to look at them and vote them up).
Like any good (modern) web page, this one has plenty of RSS feeds. This is the feed I use to watch questions tagged emacs elisp emacs-lisp dot-emacs.
Wednesday, December 10, 2008
stackoverflow.com
Posted by a at 1:24 PM 1 comments
Labels: education, emacs, link, stackoverflow, web
Monday, December 1, 2008
Emacs Tip #27: midnight-mode
I generally have a single emacs session that runs for a couple weeks, up to about 3 months (when work does it's quarterly preventative maintenance reboot), and because of this, I often have dozens of buffers open. Periodically I'd go through them and remove a bunch - mostly to free up memory.
Luckily, there's a mode that already does that for you, periodically flushing unused and old buffers:
The following variables can be used to customize the behavior of the (require 'midnight)
clean-buffer-list
(which is run daily at midnight). It responds to settings of the following variables:
I love finding packages that implement functionality I hadn't realized I wanted. It is very relieving, like accidentally scratching an itch I didn't know was bothering me.clean-buffer-list-kill-buffer-names
clean-buffer-list-kill-regexps
clean-buffer-list-kill-never-buffer-names
clean-buffer-list-kill-never-regexps
clean-buffer-list-delay-general
clean-buffer-list-delay-special
Edited to reflect proper require statement.
Posted by a at 2:38 PM 6 comments
Labels: emacs, emacs-intermediate, emacs-tip
Wednesday, October 22, 2008
Gödel, Escher, Bach
I'm a Yegge fan-boy, and his most recent post mentioned Gödel, Escher, Bach - the Pulitzer Prize-winning book by Douglas Hofstadter. Which got me to thinking...
A couple of programmers/bloggers I respect have the book on their must-have lists: Joel, Stevey. And most programming bloggers refer to it reverently.
I tried to read the book shortly after graduating college. I didn't finish it, because it was incredibly boring and repetitive and boring ... and repetitive. Turns out many don't finish the book, no surprise to me.
I'll repeat myself (in the spirit of GEB I should probably recurse), GEB was a complete snoozer. It reminded me much of Ayn Rand's Atlas Shrugged - another snoozer. There's only so much repetition I can stand.
I'm sure I missed all the puzzles and word-play - I certainly didn't get to the end where Hofstadter's characters discuss books that end before the final page (a joke that took 700 pages to set up).
Perhaps the book provides a path to enlightenment to people who are not familiar with recursion, self-reference, and the incompleteness theorem. Or, maybe there is enough wordplay and "charming" dialog to get you to wade through all 800 pages (there is that one nearly at the end).
I'd have been happier if the book were condensed to 150 pages.
Posted by a at 1:56 PM 5 comments
Friday, October 10, 2008
Emacs Tip #26: CUA mode (specifically rectangle editing)
I'd heard of CUA mode, but generally dismiss it because I don't want the "windows" bindings for cut/copy/paste/undo. But when I saw this video of CUA's rectangle support, I knew this was the way to edit rectangles.
Emacs Column Editing from Mark Mansour on Vimeo.
To activate in emacs 22.1 - with minimal intrusion (I don't like transient mark mode):(setq cua-enable-cua-keys nil)
(setq cua-highlight-region-shift-only t) ;; no transient mark mode
(setq cua-toggle-set-mark nil) ;; original set-mark behavior, i.e. no transient-mark-mode
(cua-mode)
The *info* page doesn't have the rectangle bindings (as far as I can see), so here is the documentation from the code:
;; CUA rectangle support
;; ---------------------
;; Emacs' normal rectangle support is based on interpreting the region
;; between the mark and point as a "virtual rectangle", and using a
;; completely separate set of "rectangle commands" [C-x r ...] on the
;; region to copy, kill, fill a.s.o. the virtual rectangle.
;;
;; cua-mode's superior rectangle support uses a true visual
;; representation of the selected rectangle, i.e. it highlights the
;; actual part of the buffer that is currently selected as part of the
;; rectangle. Unlike emacs' traditional rectangle commands, the
;; selected rectangle always as straight left and right edges, even
;; when those are in the middle of a TAB character or beyond the end
;; of the current line. And it does this without actually modifying
;; the buffer contents (it uses display overlays to visualize the
;; virtual dimensions of the rectangle).
;;
;; This means that cua-mode's rectangles are not limited to the actual
;; contents of the buffer, so if the cursor is currently at the end of a
;; short line, you can still extend the rectangle to include more columns
;; of longer lines in the same rectangle. And you can also have the
;; left edge of a rectangle start in the middle of a TAB character.
;; Sounds strange? Try it!
;;
;; To start a rectangle, use [C-return] and extend it using the normal
;; movement keys (up, down, left, right, home, end, C-home,
;; C-end). Once the rectangle has the desired size, you can cut or
;; copy it using C-x and C-c (or C-w and M-w), and you can
;; subsequently insert it - as a rectangle - using C-v (or C-y). So
;; the only new command you need to know to work with cua-mode
;; rectangles is C-return!
;;
;; Normally, when you paste a rectangle using C-v (C-y), each line of
;; the rectangle is inserted into the existing lines in the buffer.
;; If overwrite-mode is active when you paste a rectangle, it is
;; inserted as normal (multi-line) text.
;;
;; If you prefer the traditional rectangle marking (i.e. don't want
;; straight edges), [M-p] toggles this for the current rectangle,
;; or you can customize cua-virtual-rectangle-edges.
;; And there's more: If you want to extend or reduce the size of the
;; rectangle in one of the other corners of the rectangle, just use
;; [return] to move the cursor to the "next" corner. Or you can use
;; the [M-up], [M-down], [M-left], and [M-right] keys to move the
;; entire rectangle overlay (but not the contents) in the given
;; direction.
;;
;; [C-return] cancels the rectangle
;; [C-space] activates the region bounded by the rectangle
;; If you type a normal (self-inserting) character when the rectangle is
;; active, the character is inserted on the "current side" of every line
;; of the rectangle. The "current side" is the side on which the cursor
;; is currently located. If the rectangle is only 1 column wide,
;; insertion will be performed to the left when the cursor is at the
;; bottom of the rectangle. So, for example, to comment out an entire
;; paragraph like this one, just place the cursor on the first character
;; of the first line, and enter the following:
;; C-return M-} ; ;C-return
;; cua-mode's rectangle support also includes all the normal rectangle
;; functions with easy access:
;;
;; [M-a] aligns all words at the left edge of the rectangle
;; [M-b] fills the rectangle with blanks (tabs and spaces)
;; [M-c] closes the rectangle by removing all blanks at the left edge
;; of the rectangle
;; [M-f] fills the rectangle with a single character (prompt)
;; [M-i] increases the first number found on each line of the rectangle
;; by the amount given by the numeric prefix argument (default 1)
;; It recognizes 0x... as hexadecimal numbers
;; [M-k] kills the rectangle as normal multi-line text (for paste)
;; [M-l] downcases the rectangle
;; [M-m] copies the rectangle as normal multi-line text (for paste)
;; [M-n] fills each line of the rectangle with increasing numbers using
;; a supplied format string (prompt)
;; [M-o] opens the rectangle by moving the highlighted text to the
;; right of the rectangle and filling the rectangle with blanks.
;; [M-p] toggles virtual straight rectangle edges
;; [M-P] inserts tabs and spaces (padding) to make real straight edges
;; [M-q] performs text filling on the rectangle
;; [M-r] replaces REGEXP (prompt) by STRING (prompt) in rectangle
;; [M-R] reverse the lines in the rectangle
;; [M-s] fills each line of the rectangle with the same STRING (prompt)
;; [M-t] performs text fill of the rectangle with TEXT (prompt)
;; [M-u] upcases the rectangle
;; [M-|] runs shell command on rectangle
;; [M-'] restricts rectangle to lines with CHAR (prompt) at left column
;; [M-/] restricts rectangle to lines matching REGEXP (prompt)
;; [C-?] Shows a brief list of the above commands.
;; [M-C-up] and [M-C-down] scrolls the lines INSIDE the rectangle up
;; and down; lines scrolled outside the top or bottom of the rectangle
;; are lost, but can be recovered using [C-z].
Posted by a at 11:44 AM 5 comments
Labels: emacs-intermediate, emacs-tip
Wednesday, September 3, 2008
The Web Interface Is Morphing Into Emacs
A while back, Steve Yegge wrote a post on Emacs and its future. My executive summary of his post is that Emacs needs to compete or die - and the competition is the browser.
This got a little thread started on the Emacs development list, but not much activity. If Steve's line of reasoning is correct, then I surmise Emacs is dead b/c the Emacs development team is not at all interested in competing with the browser. Heck, they recently had a discussion on moving from CVS to a modern (distributed) version control system - and while there appears to be a tentative decision to move to Bazaar for version control, main development is still on CVS.
I personally think Emacs is a niche product. Like Unix, it has a dedicated fan base and will be around for the foreseeable future. But, it is never going to grow a large base of end-users. It has got a lot of ... baggagehistory that turns some people off: GPL, RMS, lisp, (lack of) speed, text-based, carpal tunnel, etc.
I love Emacs and do most everything inside Emacs, but it is not and probably will never be hip, exciting, new, or perceived as leading edge technology.
What was my point? Oh, right, Ubiquity was recently announced at Mozilla Labs.
I watched the 6 minute video demo. And my first impression? It is Emacs, only instead of M-x
you use C-SPC
. Soon, people will tire of typing things out and come up with shortcuts based on various key combinations, and it'll turn into Emacs.
Of course, if Ubiquity does that, it'll be cool/hip, and people won't complain about the key-bindings.
It's just like XML over Lisp. The reaction to Lisp is, "OMG! Parentheses! Run!" On the other hand, XML (with twice the number of parenthesis</>) is cool/hip and folks have flocked to it.
Steve was right about the competition, the browser has fired the first salvo, and it looks a lot like Emacs.
Mozilla Labs » Introducing Ubiquity
Posted by a at 10:27 AM 4 comments
Tuesday, August 19, 2008
Emacs Tip #25: Shell Dirtrack By Prompt
Note: I've since been notified of this problem already being solved by a package provided with Emacs. I looked at it and prefer the implementation in this post, only because it modifies the prompt so I don't have to see the full path in my prompt.
I'd been butting my head against this issue for a while now, but wasn't quite annoyed enough to come up with a solution. Luckily for me (and you), ccthomas wrote this little snippet which parses your shell prompt to determine the current directory.
Other than having to modify your shell prompt (no big deal), it's super clean and easy.
I modified the code slightly because I didn't see the need/purpose for/of the "%300<.<
" in the prompt. So here' s my slightly modified version:
(add-hook 'shell-mode-hook
#'(lambda ()
(shell-dirtrack-mode nil)
(add-hook 'comint-preoutput-filter-functions
'shell-sync-dir-with-prompt nil t)))
(defun shell-sync-dir-with-prompt (string)
"A preoutput filter function (see `comint-preoutput-filter-functions')
which sets the shell buffer's path to the path embedded in a prompt string.
This is a more reliable way of keeping the shell buffer's path in sync
with the shell, without trying to pattern match against all
potential directory-changing commands, ala `shell-dirtrack-mode'.
In order to work, your shell must be configured to embed its current
working directory into the prompt. Here is an example .zshrc
snippet which turns this behavior on when running as an inferior Emacs shell:
if [ $EMACS ]; then
prompt='|Pr0mPT|%~|[%n@%m]%~%# '
fi
The part that Emacs cares about is the '|Pr0mPT|%~|'
Everything past that can be tailored to your liking.
"
(if (string-match "|Pr0mPT|\\([^|]*\\)|" string)
(let ((cwd (match-string 1 string)))
(setq default-directory
(if (string-equal "/" (substring cwd -1))
cwd
(setq cwd (concat cwd "/"))))
(replace-match "" t t string 0))
string))
The original can be found on the Emacs Wiki: Shell Dirtrack By Prompt
Posted by a at 1:27 PM 0 comments
Labels: emacs-basic, emacs-tip, shell
Wednesday, July 30, 2008
Forcing Abstraction
I just read the post: Rail Spikes: Functional programming and looping by Jon. It's a nice post, and I completely agree - you should never write for/while/do-while loops.
My gripe here is that this post has to exist at all. Everyone should know this, it is fundamental to have collections and operate on the collection - not using indices into collections1. IMO, this should be taught from day 1 in programming courses. Kudos to Ruby for getting the syntax clean - the left to right parsing is easier on (English reading) programmers than Lisp's inside-out parsing.
It seems to me that "abstraction" is generally applied to only classes people write, and not much thought is given to the lower-level usages. In this case: looping constructs.
I find it interesting that many people won't move away from for/while/do-while loops. In my previous job, people actively resisted such efforts. I remember introducing BOOST_FOREACH into our C++ development (a poor replacement for map
, but a step in the right direction), and I had to pull teeth to get folks to use it. And, as awkward as the STL algorithms may be to use, they're still easier than rolling your own loop to remove elements.
I think Jon has taken a (permanent) step up the abstraction layer, he's moved away from thinking about the mechanics of iteration to focusing on what he wants to get done. Isn't that what we're taught in our first class on abstraction?
The main reasons people seem to give for not taking the step Jon has are:
- language doesn't support it (Java/C++/C/whatever)
- need for speed
- for loops are easy
Language. The first is legitimate, and I don't see an easy way around this. I find it sad when languages do not allow this, but my whining doesn't make the problem go away. Let's move on.
Speed. Funny how most everyone thinks their code just needs to be fast and they just know the code they're writing is fast. We should all trust Knuth when he said "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil." If you really think you're smarter than Knuth, there's nothing I can say that will ever help you.
Easy. The third point, in my opinion, boils down to short-sightedness. People can be too narrow-minded (lazy) to want to learn something new. They might not see the fact they could remove an entire class of bugs from their code, forever. Folks don't realize the visual/mental clutter for loops add to their code. And, most importantly, for loops focus on the wrong thing (the indices, as opposed to the transformation) - see abstraction.
On a related abstraction tangent, a colleague of mine at Intel started writing a geometric template library for C++. One of the guiding ideas (not novel, but perhaps pushed to the extreme) was to remove 'if' statements from the code, as well as to remove all references to X/Y/Z. As an example, you might want to know whether the points a,b,c form a concave right angle2. One way is to have four different checks looking like:
if(
a.x == b.x &&
a.y < b.y &&
b.y == c.y &&
b.x < c.x
) || ...
repeated 3 more times with slight variation. Or, you could write a one-liner like so:
bool concave = (a.towards(b).left() == b.towards(c));
Teams of people were shown this example, contrasting 20 lines of code against the one-liner, and the response was almost universally, "so? what's the problem?"
I am truly stunned and left speechless when people cannot comprehend the difference in readability/maintainability of 20 lines of (mind-numbingly-repetitive-and-error-prone) code versus one line. We can debate whether the single line is simply readable or more elegant, but surely the 20 lines can be agreed as horrific.
After finally bridging that gap, people immediately ask why the GTL library does not provide direct access to the X/Y/Z coordinates. The question is usually phrased as, "Ok, ok, the one-liner is better. But what if I want to use the X/Y version?" Nobody has given an example where the isotropic (aka coordinate-free) code fails to provide something the X/Y interface provides. Yet people still cling to wanting that interface3.
I'm of the opinion we should force the level of abstraction up.
New languages should not have for/while/do-while loops, and (in this example), a geometric library should not provide an interface to X/Y/Z coordinates.
Personally, I'd rather not work with you if you can't wrap your mind around a higher level of abstraction4.
Footnotes:
- Sure, there are occasions in high-performance code where you might need to deal directly with indices, or write a for loop, but 97% of the time you don't, so give it up.
- This example assumes manhattan geometry, a common assumption in the EDA world.
- Yes, when you draw a rectangle, it might be clearer to access the X/Y coordinates directly. However, you'd better write that code in only one location. And why isn't your graphics library providing this for you in the first place?
- Interestingly, the GTL library provides significant speed improvement over other libraries because its isotropic bent allowed it to get rid of
if
statements which kill performance. I also found this post on high level optimization interesting, as well as Yegge's talk on dynamic languages (specifically on optimizations they can make).
Posted by a at 10:04 AM 3 comments
Labels: abstraction, C++, language, lisp
Wednesday, June 4, 2008
A guided tour of Emacs
I recently came across the GNU page: A guided tour of Emacs. It is a gem of an introduction to Emacs. Unlike the help distributed with Emacs (tutorial, FAQ, *info* pages), this tour does a good job illustrating the wide variety of Emacs capabilities, and I think it is much more motivating for a newbie than anything else I've seen.
Posted by a at 3:34 PM 0 comments
Labels: emacs-basic, link
Monday, June 2, 2008
Emacs Tip #24: view-emacs-problems
M-x view-emacs-problems
Like any good tool, Emacs can tell you about problems about which it knows. I just learned something myself (see 'Emacs pauses for several seconds when changing the default font').
To see the problems file, use the keybinding:
C-h C-e
[edited to correct binding, thanks rodrigo]
Posted by a at 4:12 PM 1 comments
Labels: emacs-basic, emacs-tip
Friday, May 30, 2008
Emacs Tip #23: set-goal-column
M-x set-goal-column (C-x C-n)
Emacs generally tries to maintain the same horizontal position for the
cursor as you move up and down in the buffer. However, you may want
to have it "remember" a particular position when perusing a data file
of some sort - perhaps when a certain column has particular interest.
C-x C-n does just that. It sets the current horizontal position as
the goal column. You can move around the buffer however you want, but
as soon as you use C-n or C-p, you're moved back to the goal column.
To unset, just use the universal prefix:
C-u C-x C-n
Posted by a at 1:00 PM 0 comments
Labels: emacs-basic, emacs-tip
Tuesday, May 20, 2008
Emacs Tip #22: blink-cursor-mode
I couldn't care less about whether or not the cursor blinks. (note proper use of that phrase, rare in this culture)
However, some people really like it, need it, and some people don't like it at all. A recent thread in comp.emacs brought this to light.
So, if you'd like your cursor to blink (or not), add the line:
(blink-cursor-mode 1) ;; or pass in -1 to turn it off
to your .emacs. By default the cursor will blink.
You can also have the cursor stretch to cover the full width of the glyph (character) under it. e.g. it'd be as wide as the tab character (should there be one in your buffer):
(setq x-stretch-cursor t)
For more documentation on cursor display, read the manual.
Posted by a at 8:04 AM 0 comments
Labels: emacs-basic, emacs-tip
Monday, May 12, 2008
Emacs Tip #21: pabbrev (predictive abbreviation expansion)
pabbrev
is a yet another package for abbreviation expansion in Emacs. Unlike dabbrev
, this one analyzes the contents of the buffers during idle time, and shows potential expansions based on word frequency. This package also shows potential expansions as you are typing. For example if you were typing 'pred', this is what you would see:
p[oint]
pr[ogn]
pre[-command-hook]
pred[ictive]
A
TAB
at any time will expand the word to the shown choice. If you do not like what was chosen, you can press TAB
again and get a list of possible choices from which to chose.To use it, download the source, and add this to your .emacs:
(require 'pabbrev "/path/to/package/pabbrev.el")
(global-pabbrev-mode)
Documentation can be found in the source file. (I copied the example from the code itself.)
Posted by a at 9:55 AM 0 comments
Labels: emacs-intermediate, emacs-tip
Monday, May 5, 2008
Emacs Tip #20: Exiting Emacs
I almost never use this tip, but some might find it handy:
C-x C-cThat is the key-binding to exit emacs, it runs
save-buffers-kill-emacs
, and the documentation for exiting emacs can be read here: Exiting - GNU Emacs Manual
Posted by a at 8:29 AM 5 comments
Labels: emacs-basic, emacs-tip
Monday, April 28, 2008
Emacs Tip #19: Startup Options (-q)
The most useful two options I've found for starting up emacs are:
-q
and
-debug-initThe first disables the loading of your .emacs and default.el files, which is handy when you want to differentiate between problems in your .emacs file and problems outside (.Xdefaults, site specific .emacs, etc.).
The second gives you a backtrace when any error happens during loading of your .emacs file. While it doesn't often pinpoint the exact line where things went wrong, it usually gives you a clue as to where to start looking for problems.
For all options, read the manual here: Initial Options - GNU Emacs Manual
Posted by a at 9:11 AM 1 comments
Labels: emacs-basic, emacs-tip, link
Monday, April 21, 2008
Emacs Tip #18: Keyboard Macros
If you find yourself doing a repetitive set of keystrokes, but don't want to bother with learning how to actually write a script for that, then record a keyboard macro.
C-x ( begins recording
C-x ) ends recording
C-x e executes the last keyboard macro
C-x C-k lets you edit the keyboard macro you just wrote
If find yourself using lots of macros, you can even save them to your
.emacs and name them (for later use).
For more documentation, see the info page:
C-h K C-x (
Or check out the Keyboard Macros section in the Emacs wiki.
Posted by a at 12:43 PM 2 comments
Labels: emacs-advanced, emacs-tip
Monday, April 7, 2008
Emacs Tip #17: flyspell and flyspell-prog-mode
Being in front of the computer hasn't helped my spelling because it's so easy to let the computer catch and fix the spelling errors for me. Of course Emacs has spell checking (M-x spell-{buffer,region,string,word}
), but what is really handy is spell-checking as you type.
Enter flyspell
.flyspell
is a minor-mode, so enabling it only causes spell-checking in that buffer, so it's handy to add the hooks to turn it on for the modes you deem appropriate (mail messages, text files, etc.). But wait, you do most of your work programming, right? Just turn on flyspell-prog-mode
, and only your comments and strings will be checked for spelling errors.
It has the standard installation - only the major entry point is the routine 'flyspell-mode
where the filename is "flyspell.el", so you need to tell Emacs to look for that appropriately. Here's what I use to enable flyspell
and turn it on for a couple of different modes.
(autoload 'flyspell-mode "flyspell" "On-the-fly spelling checker." t)
(add-hook 'message-mode-hook 'turn-on-flyspell)
(add-hook 'text-mode-hook 'turn-on-flyspell)
(add-hook 'c-mode-common-hook 'flyspell-prog-mode)
(add-hook 'tcl-mode-hook 'flyspell-prog-mode)
(defun turn-on-flyspell ()
"Force flyspell-mode on using a positive arg. For use in hooks."
(interactive)
(flyspell-mode 1))
Posted by a at 10:31 AM 8 comments
Labels: emacs-basic, emacs-tip, link
Tuesday, April 1, 2008
Emacs Tip #16: check-parens
Ever had trouble finding a mismatched parentheses in a file? Of course not, you don't make mistakes.
But, if you do, you can use the built in functionality of M-x check-parens
The documentation is here Parentheses - GNU Emacs Manual
It doesn't pinpoint the problem as closely as I would have hoped in some modes, but it's better than nothing.
Posted by a at 9:11 AM 0 comments
Labels: emacs-basic, emacs-tip, link
Monday, March 24, 2008
Emacs Tip #15: indent yanked code
I'm a bit apprehensive about this chunk of code, mainly because it facilitates cut/paste coding, which I abhor. Nevertheless, it does come in handy.
When you (shudder) cut/paste code, one of the first things you do is immediately indent the code appropriately. Well, why not have that done automatically for you? This chunk of emacs lisp does the trick rather nicely.
It will not indent regions that are too large (see yank-advised-indent-threshold
) and given a prefix argument, it will not indent.
;; automatically indenting yanked text if in programming-modes
(defvar yank-indent-modes '(emacs-lisp-mode
c-mode c++-mode
tcl-mode sql-mode
perl-mode cperl-mode
java-mode jde-mode
lisp-interaction-mode
LaTeX-mode TeX-mode)
"Modes in which to indent regions that are yanked (or yank-popped)")
(defvar yank-advised-indent-threshold 1000
"Threshold (# chars) over which indentation does not automatically occur.")
(defun yank-advised-indent-function (beg end)
"Do indentation, as long as the region isn't too large."
(if (<= (- end beg) yank-advised-indent-threshold)
(indent-region beg end nil)))
(defadvice yank (after yank-indent activate)
"If current mode is one of 'yank-indent-modes, indent yanked text (with prefix arg don't indent)."
(if (and (not (ad-get-arg 0))
(member major-mode yank-indent-modes))
(let ((transient-mark-mode nil))
(yank-advised-indent-function (region-beginning) (region-end)))))
(defadvice yank-pop (after yank-pop-indent activate)
"If current mode is one of 'yank-indent-modes, indent yanked text (with prefix arg don't indent)."
(if (and (not (ad-get-arg 0))
(member major-mode yank-indent-modes))
(let ((transient-mark-mode nil))
(yank-advised-indent-function (region-beginning) (region-end)))))
Posted by a at 10:13 AM 3 comments
Labels: emacs-intermediate, emacs-lisp, emacs-tip
Thursday, March 20, 2008
Interview-1
I've written before about interviewing, but I think there's a topic people have ignored, namely that people conducting interviews forget (in my vast experience of employment in 2 companies) is that a part of the purpose of the interview is to sell the group/company to the interviewee.
Shortly after the post in August, a friend of mine started looking for jobs, he interviewed at companies X and Y, and his experiences were very different.
Let me compare and contrast the two interviews:
At company X, he was underwhelmed by the technical lead for the job (the guy is nice, but somewhat soft-spoken, so not a lot of energy/excitement), and the questions posed by all the interviewers were pretty shallow. In other words, the questions were like, "write a routine to do sorting", which he did, and then they moved on to the next question - no further investigation of why he chose that, how might he optimize it, etc. etc. etc. It sounded kind of like watching an interview on TV where the questions were all 'yes' or 'no' questions.
At company Y, the questions were very often 'deep' questions, where the initial answer was picked apart and explored. The questions also seemed to be a little more interesting and challenging - one of the guys asked my friend how he might approach a problem that the guy had been working on that entire week.
Needless to say, my friend decided against working at company X and was very tempted by company Y.
I recall my interview at Mentor, and it was somewhat similar to my friend's at company X, only I wasn't asked to write any code. I did bring some samples of what I'd written and offered them to the hiring manager. I presume the interviewers liked what they saw in me, but I was concerned because I expected to be asked to show some level of competence in the job for which I was interviewing (a programmer).
I always figured that if you're interviewing for a job at an auto-repair shop, you'd be expected to poke around an engine and show some competence. The same thing should go for a programming job. And, wouldn't you be a little concerned if you knew your mechanic didn't require a competency exam before hiring his mechanics? (See raganwald's hiring a juggler post.)
So remember, the quality of the interview you provide influences how the interviewee views the company.
Posted by a at 10:30 AM 2 comments
Monday, March 17, 2008
Emacs Tip #14: caps lock on windows
In my previous job, everyone had Windows laptops, and worked using VNC. But they never learned the trick to change the Caps Lock key into a Ctrl key.
From the GNU Emacs FAQ for Windows: "Caps"
Download caps-as-ctrl.reg to make CapsLock a Control key (leaving your original control keys as they were), or caps-ctrl-swap.reg to swap CapsLock and the left Control key. Once you've downloaded them, double-click on the .reg files in Explorer or "run" them from a command prompt to have them update your registry.If you use Emacs and you are using Windows and your Caps Lock key is still functioning as Caps Lock, just download the registry change and install it. If you really think you need to type in all caps, learn
M-x upcase-region
Posted by a at 11:31 AM 2 comments
Labels: emacs-basic, emacs-tip
Monday, March 10, 2008
Emacs Tip #13: browse-kill-ring
The kill-ring. You know about the kill-ring, right?
C-h i m emacs RET kill ring RET
Ok, now you know about the kill-ring, it is basically a list of all the chunks of text that have been cut (C-w
) (or just saved using M-w
). The basic interaction with the kill-ring is:
C-y
(aka "yank" aka "paste")
After you've pasted text, if you didn't want that, but an earlier chunk of text, the key M-y
will cycle through the earlier chunks, replacing what was just pasted with the earlier text.
If that's too much for you to handle, you can browse the entries in the kill-ring and paste them in (more than one if you want).
To get it, go to the wiki and download it.
To install and use, do the standard download, load-path manipulation, and:
(require 'browse-kill-ring)
M-x browse-kill-ring
[edited to correct the cut/paste commands]
[edited to fix broken link]
Posted by a at 8:43 AM 4 comments
Labels: emacs-basic, emacs-tip, link
Monday, March 3, 2008
Emacs Tip #12: show-trailing-whitespace
If you don't like having lines of code/text with whitespace at the
ends, you can turn on the variable 'show-trailing-whitespace' to have
Emacs highlight the offending whitespace.
When set, the variable's value becomes buffer local, so set it to true
in the mode-hooks for your preferred modes. Or, if you want it on all
the time, change the default value with:
(setq-default show-trailing-whitespace t)
Posted by a at 8:57 AM 2 comments
Labels: emacs-basic, emacs-tip
Wednesday, February 27, 2008
Arc's Out
Paul Graham recently released his new language Arc
Some think it is a great step, others think it's a big yawn, many people don't like Paul Graham for who knows what reason.
I read about half of On Lisp, and intend to read the other half at some point, because it really did open up what I thought of Lisp (and I'm already a convert).
But one thing I remember thinking when PG first mentioned Arc's progress, "Wait a minute, one of the main points in On Lisp was you can define your own syntax, so what's new/different about Arc?"
And now that it is out, and I've read the tutorial, I'm still wondering, "where's the beef?"
I've not actually done much more than glance through the downloaded source, and examined the tutorial. The tutorial is a yawn, just some new special forms with shorter names, nothing amazing. I hope the libraries packaged with arc are powerful and interesting - that is what I'd preferred to have seen in the tutorial.
So it seems a big yawn, the language itself is still Lisp, just (barely) less typing.
Posted by a at 8:40 PM 0 comments
Labels: language
Monday, January 21, 2008
Emacs Tip #11: uniquify
Do you dislike the buffer names Emacs generates when two files have the same name? e.g. "myfile.txt
" and "myfile.txt<2>
"
A package 'uniquify' changes the default naming of buffers to include parts of the file name (directory names) until the buffer names are unique.
For instance, buffers visiting the files:
/u/mernst/tmp/Makefile
/usr/projects/zaphod/Makefile
would be named
Makefile|tmp
Makefile|zaphod
respectively (instead of "
Makefile
" and "Makefile<2>
").There are other naming schemes possible.
I use this to my .emacs:
(require 'uniquify)
(setq uniquify-buffer-name-style 'reverse)
(setq uniquify-separator "/")
(setq uniquify-after-kill-buffer-p t) ; rename after killing uniquified
(setq uniquify-ignore-buffers-re "^\\*") ; don't muck with special buffers
For the *info* page,
C-h i m emacs RET s uniquify RET
Posted by a at 10:08 AM 3 comments
Labels: emacs-basic, emacs-tip
Wednesday, January 16, 2008
Teach The Hard Stuff
Coding Horror: How Should We Teach Computer Science?: "If we aren't teaching fundamental software engineering skills like deployment and source control in college today, we're teaching computer science the wrong way. What good is learning to write code in the abstract if you can't work on that code as a team in a controlled environment, and you can't deploy the resulting software? As so many computer science graduates belatedly figure out after landing their first real programming job, it isn't any good at all."I scanned the comments and most people talked about CS versus SE (Software Engineering), or what they think is most important to teach. I agree with the narrow point that computer science is different than software engineering - the former teaches the theory and fundamentals of computers, languages, and programming, while the latter focuses on how to engineer software for the real world.
To a large extent CS and SE are orthogonal. Knowing how to write code that can compile on 11 platforms, versus understanding why a regular expression cannot be used to match parenthesis are two completely different issues.
The difficulty with coming up with the "truly important" concepts that should be taught in school is that the software industry is too diverse to be able to put in a nutshell. Take, for example, Jeff's idea that "computer science students should develop software under conditions as close as possible to the real world" just doesn't make sense. What real world?
I've, thankfully, been gainfully employed as a software engineer for 12 years, and I've never had to worry about software distribution, and there are large numbers of people who have never had to think about that. Why? Because it was taken care of by other people - I simply abstract away that problem as not something I had to solve. So how would that lesson have helped me?
But even if you wanted to teach about software distribution, what kind of distribution? Should the students have to deal with a wide variety of PC builds (Windows2K, Vista, Me, XP)? What about Mac? And the ton of flavors of Unix and all their varieties? What about 32 versus 64 bit platforms? What would this really teach students? Distributing software is a pain. Fine, lesson taught, but why have to go through this for every class? Does everyone in your company know how to distribute the software you produce?
My point isn't for or against teaching about distribution of software. Almost any one topic under the umbrella of CS or SE fails to apply to all of the software industry. No matter what you are taught, you are going to learn things you never use, and you are not going to learn things you need to know to do your job.
So, what should be taught?
This reminds me of the time I asked a professor what I should study in my last year or two - as I only had a couple of slots free for non-mandatory courses. I was specifically asking about taking math versus computer science classes (I was a double major), and he advised math. Why? Because math is hard.
So we should teach math?
Um.... not quite the point.
I think that school is a good time to learn the fundamentally difficult concepts. Hopefully you'll always be surrounded by intelligent, inquisitive peers and knowledgeable mentors, but the chances are school is your best bet for being immersed in that kind of environment. Think of school as a petri dish, sure, mold can grow anywhere, but it grows really well in a petri dish.
So now software is mold?
University should teach fundamentals and fundamentally difficult concepts. So things like: data and procedural abstraction, algorithmic complexity, data structures, algorithms, and what makes up this computer (OS, hardware, compiler, network). Hmmm... sounds like the course requirements for my CS degree.
No software engineering basics?
That being said, it would have been a heck of a lot easier to do some of the course work had I known more about how to use a text editor, version control, a debugger, logging, unit testing, or (gasp) an IDE. I would definitely have appreciated some introduction to those early on. But early on the projects are so small that none of those are important and would just get in the way. It's the classic chicken-and-egg problem.
So you want both CS and CE taught?
What I really want from a new college graduate is someone who can think for himself, and has the intellectual curiosity to continually improve.
Version control, any build system, testing harness, language, or software distribution system is (IMO) much easier to learn than discerning algorithmic complexity. So, if one has to make a choice between the two, I'd choose the more difficult subject, algorithmic complexity. Some of the comments argued that people don't tend to ever learn version control, so it should be taught in school. To which I would respond, if they are the kind of person who only ever learned it superficially in the real world, they would have only learned it enough to pass the class.
Teach the hard stuff in school, and, where possible, teach software engineering skills to help the student thrive while in school.
Back to the idea of developing software at school in conditions that match the 'real world'. The real world is full of noise. I'd much rather learn the subject matter than be subjected to compiler bugs, platform differences, whiny customers, incomplete specifications, etc.
I guess it boils down to the first CS class I took in college. I loved the class, and I still think it the best introductory CS class available. Why? Because in one semester you go from knowing next to nothing about CS to learning data structures/algorithms/complexity analysis and writing a interpreter, a CPU simulator, and a compiler. One semester, and you're exposed to basically all of computer science - and not just superficially.
Scheme? You want to force me to (parse (all (the (parentheses))))?
Grow up, look past the language. Look at the concepts taught. If you want to rewrite the book using Ruby or whatever, be my guest. If the result is a class that can still fit into a semester, all the power to you. The point of using Scheme was that the language is taught in one lecture, and after that you get to learn the interesting things. Try teaching meta-programming to C++ novices (hell, try teaching it to 99% of the software community).
Yeah, but it's just a toy interpreter/compiler/CPU...
If you actually look at what is taught, you have a supremely flexible interpreter/compiler/CPU simulator, and you can vary the semantics of the language, compiler optimizations, and hardware configurations. You can explore the intricacies of each to whatever extent you desire.
I've never seen that much information packed into such a concise form that is accessible to first year students.
Whatever is taught to computer science students should be taught with a focus on that subject. Just like you should remove distractions that drag your developers down, you should remove distractions from the subjects taught in school. If you want to teach about developing software in the real world, then make a class or two that does that, or provide internships, or contribute to open source projects. If something doesn't help the student learn the subject, it gets in the way.
Posted by a at 1:41 PM 0 comments
Monday, January 14, 2008
Emacs Tip #10: sig-quote (intelligent, random signatures)
Way back when I first started using Emacs, I read email with it. A friend had some script which modified his .signature file with a random quote every 30 seconds. I thought that was kind of neat, but I wanted every email to get its own, random, quote. At the time I didn't know how to get a random number in a simple shell script, so I started writing something using Emacs directly.
A random signature wasn't enough though, I then wanted to be able to have different categories of quotes and send different people quotes from those different categories. From the documentation:
;; This mode is designed to allow a user to have quotes appended to
;; their mail and news posts according to whom/where the mail is
;; being sent. For example, one might wish to have "insightful"
;; quotes sent to Prof. Apple, and "crude" quotes to your brother
;; Sam. With this mode, upon sending a piece of mail, the email
;; addresses are scanned (this includes the To:, CC:, and BCC:
;; headers), and an appropriate quote is inserted into the letter.
Thus began my Emacs fascination.
You can download the source here.
Posted by a at 1:38 PM 4 comments
Labels: emacs-intermediate, emacs-lisp, emacs-tip, email, link
Thursday, January 10, 2008
Emacs Tip #9: Gnus/Gmail integration (using IMAP)
Like many folks, I use Google for more and more. When I noticed Google's announcement that Gmail supports IMAP, I knew I could read my Gmail from Emacs.
The question was, how do you set up the integration? The Emacs wiki had instructions on how to read email, which worked nicely. But I wanted to enable Gmail to gather the mail I sent from Emacs into its conversation groups (it's no Gnus threading, but it's a start). So how to enable that? At first I automatically Bcc'ed my Gmail account, but that was hacky. Then I noticed Gmail lets you use their SMTP server.
I found some documentation on how to use it, but it didn't work for me (wrong ports evidentially), and it was integrated differently than what I wanted.
So I used my favorite Emacs lisp feature, advice, and wrote the following snippet. It checks to see if the 'From:' address is a gmail address, in which case it uses Gmail's SMTP server.
(defadvice message-send-mail (around gmail-message-send-mail protect activate)
"Set up SMTP settings to use Gmail's server when mail is from a gmail.com address."
(interactive "P")
(if (save-restriction
(message-narrow-to-headers)
(string-match "gmail.com" (message-fetch-field "from")))
(let ((message-send-mail-function 'smtpmail-send-it)
;; gmail says use port 465 or 587, but 25 works and those don't, go figure
(smtpmail-starttls-credentials '(("smtp.gmail.com" 25 nil nil)))
(smtpmail-auth-credentials '(("smtp.gmail.com" 25 "username@gmail.com" nil)))
(smtpmail-default-smtp-server "smtp.gmail.com")
(smtpmail-smtp-server "smtp.gmail.com")
(smtpmail-smtp-service 25)
(smtpmail-local-domain "yourdomain.com"))
ad-do-it)
ad-do-it))
Note: You can also download the snippet directly.
And, as a good netizen, I updated the wiki appropriately.
Posted by a at 1:31 PM 4 comments
Labels: emacs-intermediate, emacs-tip, email
Friday, January 4, 2008
Emacs Tip #8 : markdown
I saw a post for auto-generating HTML and thought, neat trick. My preferred email client is Gnus, which already mimics that (changing *text* into text and so forth).
But how cool would it be to have both my regular text show up, as well as an HTML version (when useful) - I already write using the syntax of markdown.
Mr. O'Connor happened to choose to do integration using Python (preferred programming language). Of course I don't grok Python, so getting it to work isn't quite as easy as running the Perl version.
So I coded up similar functionality, only I also tweaked things such that only the text before the signature line is converted into HTML.
(defun mimedown ()
(interactive)
(save-excursion
(message-goto-body)
(let* ((sig-point (save-excursion (message-goto-signature) (forward-line -1) (point)))
(orig-txt (buffer-substring-no-properties (point) sig-point)))
(shell-command-on-region (point) sig-point "Markdown.pl" nil t)
(insert "<#multipart type=alternative>\n")
(insert orig-txt)
(insert "<#part type=text/html>\n< html>\n< head>\n< title> HTML version of email</title>\n</head>\n< body>")
(exchange-point-and-mark)
(insert "\n</body>\n</html>\n<#/multipart>\n"))))
Posted by a at 3:06 PM 3 comments
Labels: emacs-intermediate, emacs-tip, email, html
Wednesday, January 2, 2008
Emacs Tip #7: resolve-sym-link
It's often nice to find the true path to a file or directory. Since I work in Emacs, it's often easier to use find-file to discover the path, and then invoke this little diddy. I like having it bound to C-r
(defun resolve-sym-link ()
"Replace the string at the point with the true path."
(interactive)
(beginning-of-line)
(let* ((file (buffer-substring (point)
(save-excursion (end-of-line) (point))))
(file-dir (file-name-directory file))
(file-true-dir (file-truename file-dir))
(file-name (file-name-nondirectory file)))
(delete-region (point) (save-excursion (end-of-line) (point)))
(insert (concat file-true-dir file-name))))
(define-key minibuffer-local-completion-map (kbd "C-r") 'resolve-sym-link)
Posted by a at 9:08 AM 0 comments
Labels: emacs-intermediate, emacs-lisp, emacs-tip