summaryrefslogtreecommitdiffhomepage
path: root/blog/entry/apr22emacs.mdwn
blob: 0371d8b480d1e9a0ec84f144cfc1b555fdcd2036 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
[[!meta title="Recent additions I've made to GNU Emacs"]]
[[!tag  tech Emacs]]

Here are a few new features I've added to GNU ELPA and upstream GNU Emacs
recently.  Text is adapted from the in-tree documentation I wrote for the new
features.  Thanks to everyone who offered feedback on my patches.

# New feature to easily bypass Eshell's own pipelining

Prefixing `|`, `<` or `>` with an asterisk, i.e. `*|`, `*<` or `*>`, will
cause the whole command to be passed to the operating system shell.  This is
particularly useful to bypass Eshell's own pipelining support for pipelines
which will move a lot of data.

This has long been an obstacle when it comes to using Eshell as one's main
shell.  The new syntax is easy to use and covers a lot of different use cases.

# New Eshell module to help supplying absolute file names to remote commands

After enabling the new `eshell-elecslash` module, typing a forward slash as
the first character of a command line argument will automatically insert the
Tramp prefix.  The automatic insertion applies only when `default-directory`
is remote and the command is a Lisp function.  This frees you from having to
keep track of whether commands are Lisp function or external when supplying
absolute file name arguments.

This is another attempt to solve an Eshell papercut.  Suppose you execute

     cd /ssh:root@@example.com:
     find /etc -name "*gnu*"

and in reviewing the output of the command, you identify a file `/etc/gnugnu`
that should be moved somewhere else.  So you type

    mv /etc/gnugnu /tmp

But since `mv` refers to the local Lisp function `eshell/mv`, not a remote
shell command (unlike find(1)), to say this is to request that the local file
`/etc/gnugnu` be moved into the local `/tmp` directory.  After you enable
`eshell-elecslash`, to then when you type the above `mv` invocation you will
get the following input, which is what you intended:

    mv /ssh:root@example.com:/etc/gnugnu /ssh:root@example.com:/tmp

# `imenu` is now bound to `M-g i` globally

This is a useful command but everyone has to come up with their own binding
for it.  No longer.

# New macro-writing macros, `cl-with-gensyms` and `cl-once-only`

These two macros are quite interesting.  In the history of Common Lisp-style
macros, these are the only two macro-writing macros that have emerged as
essential tools for intermediate and advanced macrology.  Most any other
macro-writing macros are either project- or programmer-specific.  In his book
on Lisp macros [Doug Hoyte
proposes](https://letoverlambda.com/index.cl/guest/chap3.html) an alternative
to `defmacro`, `defmacro!`, which is just the same as `defmacro` except that
it builds in facilities equivalent to `cl-with-gensyms` and `cl-once-only`.
I've long wanted to have these macros available in core Emacs Lisp, too, and
now they are.

# New package on GNU ELPA: transient-cycles

Many commands can be conceptualised as selecting an item from an ordered list
or ring.  Sometimes after running such a command, you find that the item
selected is not the one you would have preferred, but the preferred item is
nearby in the list.  If the command has been augmented with transient cycling,
then it finishes by setting a transient map with keys to move backwards and
forwards in the list of items, so you can select a nearby item instead of the
one the command selected.  From the point of view of commands subsequent to
the deactivation of the transient map, it is as though the first command
actually selected the nearby item, not the one it really selected.

Protesilaos Stavrou helped me test the package and has written up [some usage
notes](https://protesilaos.com/emacs/dotemacs#h:44652046-e499-4bf1-b203-0763c7d4e993).

This is an idea I came up with in 2020, and refined in my init.el since then.
This year I made it into a package.