So, what are the best ways to do this? I know what you’re thinking - let’s just
buy an Omega Aqua Terra Worldtimer mechanical watch for $10,000 and be done with
it!1 While this will definitely get the job done and improve the looks of
your wrist immensely, there’s a cheaper and more practical option for you -
Emacs. Did you know that Emacs has a command named world-clock
that does
exactly what we want?2 If you invoke it you’ll see something like this:
Seattle Monday 11 March 02:45 PDT
New York Monday 11 March 05:45 EDT
London Monday 11 March 09:45 GMT
Paris Monday 11 March 10:45 CET
Bangalore Monday 11 March 15:15 IST
Tokyo Monday 11 March 18:45 JST
Hmm, looks OK but the greatest city in the world (Sofia, Bulgaria) is missing from
the list… That’s totally unacceptable! We can fix this by tweaking the
variable world-clock-list
:
(setq world-clock-list
'(("America/Los_Angeles" "Seattle")
("America/New_York" "New York")
("Europe/London" "London")
("Europe/Paris" "Paris")
("Europe/Sofia" "Sofia")
("Asia/Calcutta" "Bangalore")
("Asia/Tokyo" "Tokyo")))
Let’s try M-x world-clock
again now:
Seattle Monday 11 March 02:51 PDT
New York Monday 11 March 05:51 EDT
London Monday 11 March 09:51 GMT
Paris Monday 11 March 10:51 CET
Sofia Monday 11 March 11:51 EET
Bangalore Monday 11 March 15:21 IST
Tokyo Monday 11 March 18:51 JST
Much better!
By the way, you don’t really have to edit world-clock-list
, as by default it’s configured to
mirror the value of zoneinfo-style-world-list
. The choice is yours.
You can also configure the way the world time entries are displayed using world-clock-time-format
. Let’s switch to a style with shorter day and month names:
(setq world-clock-time-format "%a %d %b %R %Z")
This will result in:
Seattle Mon 11 Mar 06:06 PDT
New York Mon 11 Mar 09:06 EDT
London Mon 11 Mar 13:06 GMT
Paris Mon 11 Mar 14:06 CET
Sofia Mon 11 Mar 15:06 EET
Bangalore Mon 11 Mar 18:36 IST
Tokyo Mon 11 Mar 22:06 JST
Check out the docstring of format-time-string
(C-h f
format-time-string
) for more details, as the options here are numerous.
That’s all I have for you today. I hope you learned something useful. Keep hacking!
]]>M-x
(execute-extented-command
) -
it allows you to run any Emacs command from the minibuffer and it sounds a lot
like Emacs!1 It doesn’t get better than this… or does it?
Emacs 29 introduced a new keybinding that’s aiming to give M-x
a run for its money - namely M-X
(execute-extended-command-for-buffer
). It’s described like this:
Query user for a command relevant for the current mode, and then execute it. This is like ‘execute-extended-command’, but it limits the completions to commands that are particularly relevant to the current buffer. This includes commands that have been marked as being specially designed for the current major mode (and enabled minor modes), as well as commands bound in the active local key maps.
So, it basically narrows the list of commands that you can execute to those that
make the most sense in the context of the current buffer (mostly commands coming
from the current major mode and enabled minor modes). I can easily see it
becoming more useful than M-x
when exploring some functionality that you’re
not familiar with, as the results you’d get are narrower and you’d be more
likely to find what you’re looking for.
That’s all I have for you today. On February 29th we covered a small new feature in Emacs 29. That makes me feel good! Keep hacking!
Try pronouncing M-x
out loud. ↩
--init-dir
command-line options. According the release notes:
Emacs now supports setting ‘user-emacs-directory’ via ‘–init-directory’. Use the ‘–init-directory’ command-line option to set ‘user-emacs-directory’.
Basically, this allows you to instruct Emacs where to read its configuration from. By default that’s .emacs.d
, but with this option you can easily override the default. That’s extremely handy when you want to try out different Emacs setups. Here’s some example:
# Use Emacs Prelude
$ emacs --init-dir ~/emacs-distros/prelude
# Use Spacemacs
$ emacs --init-dir ~/emacs-distros/spacemacs
I’m guessing this command-line options will be enough for most people who casually switch between different configurations and will reduce the need for them to rely on more sophisticated tools like chemacs or with-emacs.
Admittedly, I never used any such tools and I’d just symlink different dirs to .emacs.d
, so --init-dir
will definitely improve my workflow a bit.
That’s all I have for you today! Keep hacking!
]]>dash.el
has long been a staple in the Emacs community and I give it a lot of
credit for driving some upstream API progress. By showing how many people wanted
to use dash.el
for various reasons (e.g. macros like -if-let
and -when-let
and numerous functions that transform sequences), a strong case could be made
with Emacs’s maintainers that core Emacs Lisp APIs needed to be
extended. Eventually that lead to the creation of subr-x.el
1 (bundled with
Emacs since 24.3) and seq.el
(bundled with Emacs since 26.1). The two packages
mostly obsolete dash.el
and I guess this contributed to it being used less and
less these days.
I recently took over the maintenance of the popular
Flycheck package and I’ve noticed that
it was still using dash.el
, despite targeting Emacs 26.1. As I plan to submit
Flycheck to the official NonGNU ELPA package repository, it couldn’t have
dependencies that are not present on GNU ELPA and NonGNU ELPA and I needed to
remove dash.el
. Doing so turned out to be trivial, as there were obvious built-in
alternatives for everything Flycheck was using:
-if-let(*)
and -when-let(*)
with if-let(*)
and when-let(*)
from subr-x.el
.-any?
and -first
with seq-find
, -all?
with seq-every-p
and -take
with seq-take
.And that was it! The whole process literally took me 10 minutes, most of them spent checking whether seq-find
is the right replacement for -any?
and -first
.
One small caveat to keep in mind, when depending on the built-in Emacs packages
like seq.el
, is that you should typically stick to whatever version of the
package was bundled with the version of Emacs that you target (in my case Emacs
26.1 bundles seq.el
2.20), otherwise you’ll need to declare an explicit
package dependency on the newer version. Keep in mind, however, this might
cause some issues in packages that are depending on your package, but not declaring the same dependencies.2 Transitive dependencies in Emacs are a messy topic…
So, all it all it was a very quick and easy process and I can totally recommend
to other packages that are still relying only on basic dash.el
functionality
to replace it as well. Now Flycheck is totally dependency-free and it’s ready for submission
to NonGNU ELPA!
Originally authored by yours truly. ↩
describe-function
(C-h f
) and
describe-variable
(C-h v
). Basically they display the documentation for some
function or variable. E.g. if you press C-h f
and type afterwards
describe-function
we’d get the following:
describe-function is an autoloaded interactive compiled Lisp function in
‘help-fns.el’.
It is bound to C-h f, <f1> f, <help> f, <menu-bar> <help-menu> <describe>
<describe-function>.
(describe-function FUNCTION)
Display the full documentation of FUNCTION (a symbol).
When called from Lisp, FUNCTION may also be a function object.
See the ‘help-enable-symbol-autoload’ variable for special
handling of autoloaded functions.
Probably introduced at or before Emacs version 22.1.
describe-variable
is also useful to check the current value of some variable. Here’s an example:
clojure-indent-keyword-style is a variable defined in ‘clojure-mode.el’.
Its value is ‘always-align’
I’m guessing most Emacs users are quite familiar with both commands. What I
didn’t know until recently, though, is that Emacs 25.1 introduced the related
command describe-symbol
(C-h o
), which works for both functions and
variables. I’m guessing most people would benefit from using it over the more
specific commands, as it reduces some mental overhead. (the fewer keybindings we have to remember, the better)
Bonus points - describe-symbol
also works with faces, so it’s a good replacement
for describe-face
(which doesn’t have a default keybinding). One command to rule them all!
That’s all I have for you today. Keep hacking!
]]>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
and ruby-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.
]]>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 like C-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 fledged dictionary-mode
where you can search for words (you can start it with M-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 to dict.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
:
localhost
, then dict.org after confirmation (default)localhost
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). ↩
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:
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!
]]>.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 optional set-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.
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 like compat-defun
, compat-defalias
and
compat-defmacro
(all defined in compat-macs.el
) for the backported APIs. Here are a few examples from compat-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 ↩