I saw this question on Stack Overflow asking to highlight FIXME (and similar strings) in your code, but only in comments and strings.
The current fixme-mode.el found on the Emacs Wiki is kind of clunky (it's really a major mode) and awkward to read. So I took the challenge to write a new minor-mode which answers the question.
I give you fic-mode.el. It's named fic as an acronym for Fixme In Comments.
To use it, add something like the following to your .emacs:
(require 'fic-mode)
(add-hook 'c++-mode-hook 'turn-on-fic-mode)
(add-hook 'emacs-lisp-mode-hook 'turn-on-fic-mode)
Or, you can manually start it with M-x fic-mode.
Sunday, October 10, 2010
Emacs Tip #37: fic-mode.el
Posted by
a
at
4:13 AM
9
comments
Labels: emacs, emacs-basic, emacs-tip, language
Tuesday, June 22, 2010
vc-diff tweak
For a while I've noticed that 'vc-diff (C-x v =) would pop up a buffer when there were no differences, and that buffer would just say there weren't any differences. It finally got on my nerves, so I wrote this code which works around that issue.
I don't totally understand the vc code, but parts are set up to run asynchronously, and that is what was tripping up 'vc-diff in my case. The diff would come back as identical, but at the time of the callback, Emacs had already lost the window configuration - so it was forced to pop up a buffer.
(defvar my-vc-diff-pre-diff-window-configuration nil
"place to store window configuration,
because sometimes (usually) the vc-diff does things asynchronously")
(defadvice vc-diff-internal (around
vc-diff-dont-show-diff-buffer-when-no-diff
activate)
"no changes still results in *vc-diff* buffer being shown, try to avoid that"
(setq my-vc-diff-pre-diff-window-configuration (current-window-configuration))
(let* ((res ad-do-it))
(when (or (null res)
(string-match-p "^No changes between"
(with-current-buffer "*vc-diff*"
(buffer-substring-no-properties
(point-min) (point-max)))))
(set-window-configuration my-vc-diff-pre-diff-window-configuration))))
(defadvice vc-diff-finish (after
vc-diff-finish-dont-show-diff-buffer-when-no-diff
activate)
"when buffer says no differences, revert window configuration"
(when (and my-vc-diff-pre-diff-window-configuration
(string-match-p "^No changes between"
(with-current-buffer "*vc-diff*"
(buffer-substring-no-properties
(point-min) (point-max)))))
(set-window-configuration my-vc-diff-pre-diff-window-configuration)))
Posted by
a
at
1:14 PM
4
comments
Labels: emacs, emacs-intermediate, emacs-lisp
Wednesday, April 28, 2010
Emacs Tip #36: Abort the minibuffer when using the mouse
A friend of mine loves using Emacs, but is always complaining about something. This time it's Emacs' behavior to keep the minibuffer active when you use the mouse to select another window. For example, you start doing a C-x C-f, click elsewhere, and do the C-x C-f again. Emacs will beep and tell you Command attempted to use minibuffer while in minibuffer.
After swallowing my, "well don't use the mouse" response I set about trying to fix it. I'm sure this has been solved before, I just didn't have enough google-fu to find the solution.
(defun stop-using-minibuffer ()
"kill the minibuffer"
(when (and (>= (recursion-depth) 1) (active-minibuffer-window))
(abort-recursive-edit)))
(add-hook 'mouse-leave-buffer-hook 'stop-using-minibuffer)
Edited to add:
A commenter suggested using recursive minibuffers. I think that the resulting behavior is more confusing than helpful.
Yes, it avoids the error, but then you get this ever-increasing stack of minibuffers building up. If/when the user notices the minibuffer hanging around it'll be annoying (I've had people ask, "Why is it trying to find a file?" (because the minibuffer still shows Find file: /path/to/somewhere)). And heaven forbid they click in the minibuffer, type C-g and get back to the window configuration they were looking at when they started that command, which was ... 15 minutes ago.
Posted by
a
at
12:24 PM
15
comments
Labels: emacs, emacs-basic, emacs-tip
Saturday, February 20, 2010
Emacs Tip #35: framemove
Ever wanted to easily navigate between frames? Perhaps using arrow keys? Surprisingly, this didn't exist before (AFAIK).
I wrote the package framemove to have the same usage as Emacs' built in windmove package. And, even better, it can integrate with windmove so that when you run out of windows to move between, you'll jump to the next frame in that direction.
To install framemove on its own:
(require 'framemove)
(framemove-default-keybindings) ;; default prefix is Meta
But you might want to use this in conjunction with
windmove, in which case this is the integration code to add to your .emacs:
(require 'framemove)
(windmove-default-keybindings)
(setq framemove-hook-into-windmove t)
With the integration with
windmove, you just do SHIFT-right to move focus to the window to the right of the current, and when there are no more, focus will shift to the frame to the right.Switching frames is a little more challenging than switching windows - mostly because windows are simply rectangular divisions of a window - it is easy to tell what window (if any) is to the right of the point. For frames, the answer is ambiguous because the placements of frames is free-form, and frames can overlap. I think this initial implementation does a reasonable job of choosing which frame to select. It first tries the frame directly in line with the point, and if one doesn't exist, it then uses the distance between the point (projected onto the edge of the current frame) and the frames in the given direction, and after that it just tries any frame that extends beyond the current frame in that direction.
Check it out.
Currently, when focus shifts to a new frame - the point does not change inside the frame.
Posted by
a
at
12:37 AM
10
comments
Labels: emacs, emacs-basic, emacs-tip
Thursday, February 11, 2010
Emacs Tip #34: line-beginning-position, line-end-position
Such a simple thing - finding the position of the beginning or end of the current line. I've been completely oblivious to the existence of the functions line-beginning-position and line-end-position.
They return the position of the beginning or end of the current line.
They both accept an optional argument, which has the same
meaning as the argument to beginning-of-line or end-of-line.
They were first introduced in Emacs 20, in the middle of 2006. Which means I've been unnecessarily typing this for 4 years:
(save-excursion
(beginning-of-line)
(point))
Posted by
a
at
5:19 PM
2
comments
Labels: emacs, emacs-basic, emacs-lisp
Wednesday, December 23, 2009
Emacs Paper from 1981
It's been a while since I read RMS's paper on Emacs. Back in 1981, I still had another 2 years before I even saw my first computer. Reading the paper gives some insight into some of the issues they were trying to solve (real time display, extensibility, portability).
The first thing that came to mind when I first read this paper was that (to an outsider at least) Emacs really hasn't changed fundamentally since 1981 - the basic structures have held up well. I don't see any mention of subprocesses in the original paper, so that's something pretty fundamental that is new (since 1981). Of course the other obvious additions are MULE, image support, fonts, and the graphical interface.
Amusingly, vi was not mentioned in the Other Interesting Editors section. From reading the wikipedia article on vi, it certainly was available (it's a part of the Unix standard).
But what really struck me as interesting and powerful was the decision to use dynamic binding. I'd remembered playing with the differences between dynamic and lexical scoping in my SICP class in college, but never saw a reason to use it. Well, it totally fits when you want to customize Emacs' behavior.
The paper is certainly worth the 10 minutes it takes to read.
Wednesday, September 30, 2009
Emacs Tip #33: paredit
I recently found paredit. It is a mode which allows you to edit s-expressions (sexps) in a structured way.
Essentially it forces you to maintain balanced parentheses by always inserting/deleting matched pairs. It is very easy to modify the current sexp to: enclose (wrap) the next element, to merge it up one level (aka splice, i.e. remove a set of parentheses), to split the current sexp, etc.
It works with round parens (), square brackets [], curly braces {}, and angle braces <>. It also handles string quotes " the same way.
Deleting and killing of text also works nicely. For example, C-k is bound to 'paredit-kill which has the following behavior (note: | represents the cursor position):
(foo bar)| ; Useless comment!It's taking a little getting used to, but I'm finding myself thinking less about where the current block of code ends than I used to. The parentheses just take care of themselves...
->
(foo bar)|
(|foo bar) ; Useful comment!
->
(|) ; Useful comment!
|(foo bar) ; Useless line!
->
|
(foo "|bar baz"
quux)
->
(foo "|"
quux)
This is how I enabled it:
(defun turn-on-paredit-mode ()
(paredit-mode +1))
;; I didn't like C-j being overridden, I want it to still work the old way in lisp-interaction
(eval-after-load "paredit"
'(progn
(define-key paredit-mode-map (read-kbd-macro "C-j") nil)))
(add-hook 'emacs-lisp-mode-hook 'turn-on-paredit-mode)
The cheat sheet is probably the best way to get an idea of what is possible. Check it out here. Also, the command documentation is very complete (see the above which was grabbed right from the
C-k documentation, so it's easy to remind yourself what is possible.About the only problem I've had is when I've yanked code that has unbalanced parens. So I wrote a little advice which at least warns you and allows you to abort if the yanked text is unbalanced. It's not perfect, but it is a reasonable first implementation:
(defun paredit-check-region-for-yank ()
"run after yank and yank-pop to verify balanced parens"
(when paredit-mode
(save-excursion
(save-restriction
(narrow-to-region (point) (mark))
(condition-case nil
(check-parens)
(error
(if (not (y-or-n-p "The text inserted has unbalanced parentheses, continue? "))
(delete-region (point-min) (point-max)))))))))
(defadvice yank (after yank-check-parens activate)
(paredit-check-region-for-yank))
(defadvice yank-pop (after yank-pop-check-parens activate)
(paredit-check-region-for-yank))
Posted by
a
at
8:57 PM
5
comments
Labels: emacs-advanced, emacs-tip, lisp