Content AND Presentation

2017-06-17 Ways in which Emacs selects the major mode

It is well-known that Emacs can select the major mode of a file depending on the file extension. It is probably lesser-known that this is only the fourth (!) step of deciding which major mode to use. Consult the "Choosing modes" section of the Emacs manual for the details. Here, I’d like to mention one particular case where I needed to look there.

I really prefer js2-mode to the regular js-mode, if only for its indenting capabilities. Therefore, I have this in my init.el:

(add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))

I was therefore quite astonished to find out that when opening some Node.js scripts (with the .js extension), Emacs chose the default js-mode. It turned out that the culprit was the hashbang. This way I learned about the interpreter-mode-alist variable, and added this to my init.el:

(add-to-list 'interpreter-mode-alist '("node" . js2-mode))

Head to the linked section of the manual to find other ways to make Emacs use exactly the mode you want it to use. (It turns out that it is a very general mechanism – you can even write your own function to select the mode!).

CategoryEnglish, CategoryBlog, CategoryEmacs

Comments on this page

2017-06-12 smart-next-window-or-buffer

Some time ago, I wrote about an Emacs command I started to use to switch between windows (if there is more than one of them) or buffers (otherwise). While it has proven very useful, since then I started to use multiple frames. It turned out that my command wasn’t all that useful then: it couldn’t switch to a buffer in another frame.

I then decided to bind f6 to next-multiframe-window from windmove.el, and it worked better. However, there was still one gotcha: sometimes I wanted it to switch to another window in the same frame, and it switched to another frame instead.

Well, how to teach Emacs what I really wanted? First I had to formalize it myself. Turns out, it was pretty simple. What I wanted was this:

  • If there is one window in the current frame, switch to another buffer in the same window.
  • Otherwise, switch to the next window.
  • On the other hand, if there is more than one frame, and the previous cases eventually caused the command to switch back to the buffer/window it started from, switch to another frame.

Quite unexpectedly, the task of coding that was more difficult than I thought. The reason for that turned out to be the fact that other-buffer behaves strangely when the same buffer is visible in more than one frame (by default, it avoids such buffers). Of course, this being Emacs, by giving suitable parameters this behavior could be overridden. See the source and the relevant docstrings for details.

(defvar snwob-starting-window-or-buffer nil)

(defun snwob-single-buffer-p ()
  "Return non-nil if the current frame has one buffer only."
  (null (cdr (buffer-list (selected-frame)))))

(defun snwob-single-frame-p ()
  "Return non-nil if the selected frame is the only one."
  (null (cdr (frame-list))))

(defun snwob--current-window-or-buffer ()
  "Return the current buffer if there is a single window.
Otherwise, return the selected window."
  (if (one-window-p)
	  (current-buffer)
	(selected-window)))

(defun snwob--other-frame-or-window-or-buffer ()
  "Switch to the other frame if there is more than one.
Otherwise, call `snwob--other-window-or-buffer'."
  (if (snwob-single-frame-p)
	  (snwob--other-window-or-buffer)
	(other-frame 1)
	(setq this-command #'other-frame)))

(defun snwob--other-window-or-buffer ()
  "Switch to another window if there is one.
Otherwise, switch to the other buffer."
  (cond ((one-window-p)
	 (switch-to-buffer (other-buffer (current-buffer) t (selected-frame))))
	(t
	 (other-window 1))))

(defun smart-next-window-or-buffer ()
  "Switch to the other buffer if there is one window only.
Otherwise, switch to another window.  After a full cycle of two
buffers (or as many windows as there are in the selected frame)
switch to another frame."
  (interactive)
  (cond ((eq last-command #'smart-next-window-or-buffer)
	 (if (eq snwob-starting-window-or-buffer (snwob--current-window-or-buffer))
		 (snwob--other-frame-or-window-or-buffer)
	   (snwob--other-window-or-buffer)))
	(t
	 (setq snwob-starting-window-or-buffer
		   (snwob--current-window-or-buffer))
	 (snwob--other-window-or-buffer))))

(global-set-key (kbd "<f6>") #'smart-next-window-or-buffer)

I have changed f6 to this command in my init.el and I’ll see whether it’s going to stick.

CategoryEnglish, CategoryBlog, CategoryEmacs

Comments on this page

2017-06-05 More Dired goodies

Some time ago I wrote about a few nice Dired features. Recently, I decided to look at the Dired chapter of the Emacs manual, and I discovered even more of them.

For instance, a few months ago Oleh Krehel wrote about his ediff/Dired setup. I liked it a lot, and I copied his code (with one small change: I changed ediff to plain diff, which I prefer due to its simplicity). It turned out, however, that Dired has a very similar thing built in. Many of you may know that if you put point on a “new” file in Dired and press = (the “equals” sign), Emacs will ask for the “old” file and perform a diff between them. It is perhaps less known that if the pointed file has a backup, it will be used as the default “old” file. Even better, if you have active region, then the file the mark is on will be the default suggestion for the “old” file. It is still less convenient than Oleh’s solution, but it’s there.

Another nice thing I learned are the dired-do-isearch and dired-do-isearch-regexp commands, bound to M-s a C-s and M-s a M-C-s. They do exactly what they say on the tin: you mark several files (using one of the many marking commands in Dired), and then perform an isearch (string- or regex-based) on all these files. You can also do a non-incremental regex search on marked files (dired-do-find-regexp, A) or even a multi-file regex query-replace (dired-do-find-regexp-and-replace, Q).

If you think that’s all Dired can do, well, I barely scratched the surface. There’s a lot more than that. (Check out dired-maybe-insert-subdir, i, and the wole sections on subdirectories for a powerful set of commands letting you put more than one directory in a Dired buffer at the same time, for instance!) I really encourage you to read through the Dired chapter in the Emacs manual – it won’t take more than 20 minutes, and it may save you a lot of time later.

Happy direding;-).

CategoryEnglish, CategoryBlog, CategoryEmacs

Comments on this page

More...

CategoryEnglish, CategoryBlog