Posts
Emacs 29.1 Released
Today is a great day for Emacs - Emacs 29.1 has just been released1! Every Emacs release is special, but I haven’t been so excited about a new version of Emacs in ages. Why so?
Reason #1 - pure GTK front-end (a.k.a.
pgtk
). This also means that now Emacs supports natively Wayland. Which in tern means that it’s easier than ever to run Emacs in Windows’s WSL. This is huge!Reason #2 - built-in support for the massively popular Language Server Protocol via eglot.
eglot
has existed for a while, but it’s nice to see it bundled with Emacs going forward. This will certainly make Emacs better positioned to complete with “modern” editors like VS Code.Reason #3 - built-in support for TreeSitter. This means that a few years down the road we’ll have many Emacs major modes that are much faster, more robust and feature-rich. It’s infinitely easier to built a major mode using a real parser instead of using regular expressions.2 Lots of built-in modes have already been updated to have a version using
TreeSitter
internally (e.g.c-ts-mode
,typescript-ts-mode
,python-ts-mode
andruby-ts-mode
). Frankly, I can’t think of a bigger improvement in Emacs in the almost 20 years I’ve been an Emacs user. Exciting times ahead!You can read all about the new release here. I’ll likely write a few articles about some of the new features in the weeks and months to come. In Emacs We Trust! M-x Forever!
P.S. Feel free to share in the comments what are you most excited about.
Looking Up Words in a Dictionary
In recent years I grew quite used to the functionality presented by e-readers, some browsers and other tools to look up quickly a word in a dictionary while you’re reading something.1 English is not my first language and from time to time I come across something I don’t know, so I appreciate being able to figure it out quickly. That’s also a great way to learn new words and improve your vocabulary.
Turns out Emacs 28 has introduced some pretty similar functionality with the command
dictionary-lookup-definition
that will lookup the word at point. You can bind this command to something likeC-c l
(l
for “lookup”):(global-set-key (kbd "C-c l") #'dictionary-lookup-definition)
This command is part of the much bigger
dictionary
package, that is full of all sorts of features - e.g. a fully fledgeddictionary-mode
where you can search for words (you can start it withM-x dictionary
). Lots of cool features there, but I need only the lookup word at point functionality most of the time.One thing to keep in mind is that by default Emacs will try to use a locally installed dictionary server (
dictd
) and fallback todict.org
if such a server is not available. Installing the server is quite easy (the instructions below are for Debian and friends):$ sudo apt-get install dictd dict dict-{wn,vera,jargon,devil,gcide,foldoc} $ sudo systemctl enable dictd
The above command will install the dictionary server and some common dictionaries. But if you’re lazy like me, you can just force the use of
dict.org
all the time:(setq dictionary-server "dict.org")
You’ve got the following options for
dictionary-server
:- Automatic: First try
localhost
, then dict.org after confirmation (default) - localhost: Only use
localhost
- dict.org: Only use dict.org
- User-defined: You can specify your own server here (e.g. “mydict.org”)
Choose wisely!
That’s all I have for you today. Now you have one less reason to leave the comfort of Emacs and you’ll get to learn a lot of new words quickly! Keep hacking!
-
I think the Kindle introduced to me this feature and macOS made me a huge fan of it (there you can access the macOS dictionary from pretty much every app that does something with text). ↩
- Automatic: First try
Emacs Redux Turns 10
Last month marked 10 years since I’ve started “Emacs Redux”. The blog’s mission I outlined in the very first post was the following:
It’s time to bring Emacs under the spotlight once more and showcase its unique advantages over the more “traditional” (conventional) text editors and integrated development environments.
Welcome to Emacs Redux! In this blog, dedicated to the One True Editor, I’ll be sharing with you useful tips and tricks to make your experience with Emacs more productive and more enjoyable.
In hindsight it’s hard to say whether I did well or not. I certainly shared a lot of tips and tricks. Many of the handy commands I’ve introduced in the early articles ended up in the crux package. On the other hand - I don’t think I did much exploration of the fundamental strengths of Emacs. Oh, well - you can’t win them all!
The blog had some ups and downs and some years I wrote almost nothing here. I guess this was a reflection of my level of inspiration, shifting interests, priorities and various life challenges. Today I don’t use Emacs nearly as much as when I started “Emacs Redux”, but it’s still an integral part of my toolbox and I still love it. And I still enjoy sharing Emacs tips and tricks that I discover on the life-long journey called “mastering Emacs”.
Some random trivia & stats:
- I wrote 188 articles in total here
- 2013 was my most productive year with 68 (!!!) articles
- 2017 was my least productive year with only 2 articles (written on 31.12)
- Seems that my most popular Emacs Redux articles ever are about using Emacs with WSL (e.g. this one)
- Emacs Redux started as an attempt to spin-off the Emacs content from my original personal blog. Funny enough all of my “essays” on Emacs still ended up there.
- I’ve started to use Emacs in 2005 on my first programming gig (I was a C programmer back then)
- In the period 2004-2005 (my first year working in Unix) I was a vim user
- I wrote my first blog post about Emacs in 2008
- Projectile and Emacs Prelude were my first major OSS projects
- Emacs it the One True Editor that will bring balance to the Source
When I draw the line probably I’m the person who learned the most from “Emacs Redux”, which is fine by me. I can only hope that some of my dear readers found something of value here as well. I make no promises for the future, but I’ll do my best to keep “Emacs Redux” alive (and useful) for another decade to come. In Emacs we trust! M-x forever!
Setting the Default Font for Emacs
Even after almost 20 years of using Emacs I keep learning new things about it. I’ve always known that if you’re using Emacs on Linux the best way to set the default font is via the file
.Xresources
. Here’s some random example:Emacs.font: Iosevka Term Curly:weight=regular:size=14
But I’ve got several computers and I use Emacs on macOS, Linux (I consider WSL Linux as well) and occasionally natively on Windows. That’s why I’ve historically preferred to use just the font in my
init.el
like this:;; the font size here is huge, because it's for X on a HiDPI screen ;; X can't handle font scaling properly, therefore I just double the font size ;; when I have to use Emacs under X (set-frame-font "Cascadia Code 28")
I recently, however, noticed that under X child frames are not using the same font and looked a lot smaller.1
I was sure this had something to do with X not handling HiDPI screens properly, but it wasn’t immediately obvious to me why was the font in the child frame different from the font used in the primary Emacs frame.
Turned out that
set-frame-font
by default doesn’t apply to child frames of the main frame. Fortunately you can easily address this by specifying an optionalset-frame-font
parameter:(set-frame-font FONT &optional KEEP-SIZE FRAMES INHIBIT-CUSTOMIZE)
Set the default font to FONT. When called interactively, prompt for the name of a font, and use that font on the selected frame. When called from Lisp, FONT should be a font name (a string), a font object, font entity, or font spec.
If KEEP-SIZE is nil, keep the number of frame lines and columns fixed. If KEEP-SIZE is non-nil (or with a prefix argument), try to keep the current frame size fixed (in pixels) by adjusting the number of lines and columns.
If FRAMES is nil, apply the font to the selected frame only. If FRAMES is non-nil, it should be a list of frames to act upon, or t meaning all existing graphical frames. Also, if FRAMES is non-nil, alter the user’s Customization settings as though the font-related attributes of the ‘default’ face had been “set in this session”, so that the font is applied to future frames.
If INHIBIT-CUSTOMIZE is non-nil, don’t update the user’s Customization settings.
So, in the end all I needed to do was:
(set-frame-font "Cascadia Code 28" nil t)
Magic! Now the child frames had exactly the same font as the rest of my Emacs!
Another Emacs lesson learned. That’s all I have for you today. Keep hacking!
P.S. By the way, if someone knows that does
KEEP-SIZE
do exactly please share this in the comments section. I’m utterly baffled by its description.The Compat Elisp Library: A Package Maintainer's Best Friend
I guess every package maintainer has been in the following situation - an upcoming version of Emacs introduces some new cool API that you’d like to use immediately. Or simply you have to maintain compatibility with many old Emacs versions, but you’d still like to use some modern APIs. Usually what happens in this case is that people start to backport themselves whatever Elisp APIs they need. E.g. for a long time CIDER had a file named
cider-compat.el
that looked something like this right before it became obsolete:(eval-and-compile (unless (fboundp 'if-let*) (defmacro if-let* (bindings then &rest else) "Process BINDINGS and if all values are non-nil eval THEN, else ELSE. Argument BINDINGS is a list of tuples whose car is a symbol to be bound and (optionally) used in THEN, and its cadr is a sexp to be evalled to set symbol's value." (declare (indent 2) (debug ([&or (&rest (symbolp form)) (symbolp form)] form body))) `(let* ,(internal--build-bindings bindings) (if ,(car (internal--listify (car (last bindings)))) ,then ,@else)))) (unless (fboundp 'when-let*) (defmacro when-let* (bindings &rest body) "Process BINDINGS and if all values are non-nil eval BODY. Argument BINDINGS is a list of tuples whose car is a symbol to be bound and (optionally) used in BODY, and its cadr is a sexp to be evalled to set symbol's value." (declare (indent 1) (debug if-let*)) `(if-let* ,bindings ,(macroexp-progn body))))) (provide 'cider-compat)
I’ve done something similar for many packages and I’ve seen it in the wild countless times. But there is a better and simpler way to get access to those newer APIs - enter the compat library.
Compat
is the Elisp forwards compatibility library, which provides definitions introduced in newer Emacs versions.1 The definitions are only installed if necessary for your current Emacs version. If Compat is compiled on a recent version of Emacs, all of the definitions are disabled at compile time, such that no negative performance impact is incurred. The provided compatibility implementations of functions and macros are at least subsets of the actual implementations. Be sure to read the documentation string and the Compat manual.Not every function provided in newer versions of Emacs is provided here. Some depend on new features from the C core, others cannot be implemented to a meaningful degree. Please consult the Compat manual for details regarding the usage of the Compat library and the provided functionality.
The main audience for this library are not regular users, but package maintainers. Therefore no commands, user-facing modes or user options are implemented here.
The above description is taken verbatim from the package and I don’t really have much to add to it. Here’s also what one of the package’s maintainers has to say about it and its use-cases:2
Over time Emacs has seen useful standard library additions, for example additional
string-*
functions or the newkeymap-*
functions in Emacs 29. Compat provides many of these new functions and closes the gap between Emacs core development and package development outside of Emacs, since new Emacs additions become available early for all package developers.Packages outside of Emacs core can be written in the same style as Emacs core packages by relying on Compat. Vice versa Emacs core packages can use Compat for their separate GNU ELPA releases, as is done for example by ERC, the Emacs IRC client. Compat should make it easy to move packages out of core or into the core, while still allowing separate GNU ELPA releases. Using Compat may increase the performance of your packages, since you can use optimized functions like ntake, which will only fallback to a slower compatibility version on older Emacs versions.
In a nutshell
compat
bridges the gap between what’s available for built-in Emacs packages and third-party (external) packages. And this is totally awesome!I can recommend checking out the source code of the library and its extensive changelog. You’ll notice how internally the code is organized in files matching various Emacs versions (e.g.
compat-25.el
,compat-26.el
, etc) and that the library makes heavy use of custom macros likecompat-defun
,compat-defalias
andcompat-defmacro
(all defined incompat-macs.el
) for the backported APIs. Here are a few examples fromcompat-29.el
:(compat-defun list-of-strings-p (object) ;; <compat-tests:lists-of-strings-p> "Return t if OBJECT is nil or a list of strings." (declare (pure t) (side-effect-free t)) (while (and (consp object) (stringp (car object))) (setq object (cdr object))) (null object)) (compat-defun plistp (object) ;; <compat-tests:plistp> "Non-nil if and only if OBJECT is a valid plist." (let ((len (proper-list-p object))) (and len (zerop (% len 2))))) (compat-defun delete-line () ;; <compat-tests:delete-line> "Delete the current line." (delete-region (pos-bol) (pos-bol 2))) (compat-defmacro with-restriction (start end &rest rest) ;; <compat-tests:with-restriction> "Execute BODY with restrictions set to START and END. The current restrictions, if any, are restored upon return. When the optional :label LABEL argument is present, in which LABEL is a symbol, inside BODY, `narrow-to-region' and `widen' can be used only within the START and END limits. To gain access to other portions of the buffer, use `without-restriction' with the same LABEL argument. \(fn START END [:label LABEL] BODY)" (declare (indent 0) (debug t)) `(save-restriction (narrow-to-region ,start ,end) ;; Locking is ignored ,@(if (eq (car rest) :label) (cddr rest) rest)))
And that’s a wrap. I think pretty much every package maintainer can benefit from this library in their packages (unless they have aversion to external dependencies that is). I have to admit that I learned about its existence only recently and I can’t believe I missed something so useful for so long. Mistake corrected! Keep hacking!
-
“Newer” here means means Emacs 25+. Compat itself supports Emacs 24.4+. ↩
-
Taken from https://www.reddit.com/r/emacs/comments/10iep0o/compat_29130 ↩
-
Subscribe via RSS | View Older Posts