Server Setup
I use Nix to install latest software, chezmoi to manage configuration files, and starship and fastfetch for my shell (zsh).
fd
is installed as a dependency for Doom Emacs, and mosh is used with Blink to provide UDP roaming capability.
- Install the packages above.
- Add
unset SSH_TTY
to.zprofile
. This is a workaround for clipboard integration. See tty and https://github.com/blinksh/blink/issues/1957. - Set up starship and fastfetch in
.zprofile
. - Alias
emacs
toenv TERM=vscode-direct emacs
for 24-bit color in mosh (without tmux). This requires a recent version of ncurses, see details and how to configure tmux below. - Set up Doom Emacs according to https://github.com/doomemacs/doomemacs.
- Add
(:if (featurep :system 'linux) (tty +osc))
to:os
indoom/init.el
for clipboard integration. - Add
(add-hook 'tty-setup-hook #'mouse-wheel-mode)
todoom/config.el
for mouse wheel support. - For
C-i
in Evil to “work” in terminal, add the following todoom/config.el
.
- If you need arrow keys, avoid mapping
M-O
, butM-o
is fine. See LispyVille.
- Emojis can cause cursor offset and screen state corruption in a mosh session. Replace them with Font Awesome icons that have the same width as regular icons could fix the issue.
Take lsp-mode for example, this replaces the progress and code action icons:
- If Doom Emacs throws
Lisp error: "Note: file is write protected"
whenSPC h f
let*
is pressed, it is likely because files in the nix store haver--r--r--
permissions and can be safely ignored. See backtrace below captured withdebug-on-message
.
after-find-file(nil t)
find-file-noselect-1(#<buffer eval.c> "/nix/store/wl840kj5v3f17ns5p685g1p61xdk7sc0-emacs-..." nil nil "/nix/store/wl840kj5v3f17ns5p685g1p61xdk7sc0-emacs-..." (55171408 64512))
find-file-noselect("/nix/store/wl840kj5v3f17ns5p685g1p61xdk7sc0-emacs-nox-29.1/share/emacs/29.1/src/eval.c")
helpful--open-if-needed("/nix/store/wl840kj5v3f17ns5p685g1p61xdk7sc0-emacs-...")
helpful--definition(let* t)
#<subr helpful-update>()
apply(#<subr helpful-update> nil)
helpful-update()
helpful--update-and-switch-buffer(let* t)
helpful-callable(let*)
funcall-interactively(helpful-callable let*)
command-execute(helpful-callable)
If you find it annoying, define the following advice in doom/config.el
.
24-bit color
toe -a
lists all available terminal types in the system terminfo database.
You could use this script to check color support in your terminal. “True color gradient” should have a different color under each slash or backslash character and form a smooth gradient.
For emacs installed with Nix, vscode-direct
is supported and can be verified with the following command.
In case of mosh (without tmux), vscode-direct
has to be used, because mosh does not understand SGR colon syntax yet.
You can add the following to .zprofile
to apply it to Emacs. env
command is used to avoid TERM
affecting your shell in case its terminfo database is older.
alias emacs="env TERM=vscode-direct emacs"
For tmux, set the following in ~/.tmux.conf
. terminal-overrides
ensures colors work correctly, and tmux-direct
is set as TERM
and passed to applications. This works over both mosh and regular ssh.
set-option -s default-terminal "tmux-direct"
set-option -sa terminal-overrides ",xterm-256color:Tc"
Run M-x list-colors-display
to display the Emacs-defined colors supported. Under xterm-256color
it should end in color-255
, and under xterm
there are only 8 basic colors.
For more information, see https://chadaustin.me/2024/01/truecolor-terminal-emacs/.
Bottom-right corner not filled
The point is that Emacs needs to prevent writing to the last character cell to avoid scrolling to the next line.
See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57607. Patches were proposed, but not verified yet.
Client Setup
Blink
- Install Blink
- from App Store, or
- build Blink from source, and
- with modifications (subject to change), Blink can be sideloaded with AltStore.
- Select JetBrains Mono Nerd Font in
Settings > Keyboard > Custom Presses
for icons in Doom Emacs. - If your external keyboard does not have an Esc key, in
Settings > Keyboard > ^ Control
set Press Send to “Escape on Release” and in iOS settings map Caps Lock Key to Control. - For
C-SPC
to work (IME switching shortcut in iOS), add a custom press inSettings > Keyboard > Custom Presses
with a press action of the same combo. - If you need hyper or super modifier keys for several key combos in Emacs, add a custom press. For example, hex code
1840732F
(i.e.C-x @ s /
) is equivalent tos-/
, in which18
is a control characterCAN
as defined in ASCII. This is an Emacs-only workaround and works for other modifiers as well (e.g.C-;
withC-x @ c
).
Key | Hex Code | Custom String |
---|---|---|
C-S-j | 1840530A | \x18@S\n |
C-S-k | 1840530B | \x18@S\v |
C-; | 1840633B | \x18@c; |
s-/ | 1840732F | \x18@s/ |
C-SPC | N/A (C-SPC ) |
Tips
- Mosh sessions in Blink can survive device locks, even reboots. The drawback is that you need
tmux
to get scrollback. - To show the Context bar in Blink, tap the iOS Home Bar twice or press
Cmd
twice. config
is available as a command or via shortcutCmd+,
.
Custom Presses
- Hyper and super modifiers does not work without custom press config. See https://emacs.stackexchange.com/a/5718.
C-S-
keys does not work without custom press config, e.g. in Vertico. See https://emacs.stackexchange.com/a/32295.- Modifiers you can use without custom press is Ctrl (valid control characters only), Esc (i.e. Alt, because
M-a
isESC a
), and Shift (letters and keys with upper characters only, and output is capital letters or the alternative “upper” character). - You can’t add two modifiers in the custom press trick we made use of in Emacs, but
C-<any letter>
as a control character can count as one key, soC-S-j
is still possible asC-x @ S \n
. C-i
as a special case is still translated toTAB
in Emacs, but we can re-bind theTAB
key in Emacs.C-x
does not have a special ANSI-C quoting, but we could use\x18
in Custom String format, e.g.\x18@s/
fors-/
.C-;
is not a control character, and therefore need a custom press to work in Emacs.
External Display
- When connected to an external display, Blink automatically creates a separate window on it. Press
Cmd+O
to switch there or back. See also https://docs.blink.sh/basics/tips-and-tricks#display-what-is-blink-window.- If you don’t want this, change
Settings > Appearance > External Display
to None or Mirror. The default is Scale.
- If you don’t want this, change
- You can set up a Mac to become an AirPlay Receiver. This is also treated as an external display in Blink. https://support.apple.com/guide/mac-help/mchleee00ec8/mac
- Note that Airplay is exclusive. You can’t multitask with other Mac apps while Airplaying.
- After several disconnects,
Cmd+O
might not be able to switch focus to the external display. Restarting Blink fixes it, but SSH connections would not persist through it.
Other Known Bugs
- (source build only) On some external keyboards,
j
autorepeats, butw
does not. This is related to iOS’s accent feature, wherej
does not have any corresponding accent character. https://github.com/blinksh/blink/issues/1965 - Emoji in PS1 causes cursor offset. See https://github.com/vercel/hyper/issues/2587 and https://github.com/blinksh/blink/issues/456.
- (source build only) Smart Keys not showing up in some cases.
- (third-party keyboard only?)
Cmd
key could be stuck when switching between apps. See https://docs.blink.sh/faq#cmd-key-stuck-while-switching-between-apps-with-cmd-tab. - When editing an existing custom press of type “Custom String”, if the type is changed to “Hex Code”, it will be reverted if I go back one level and try to input the hex code. Going back two levels will be OK. https://github.com/blinksh/blink/issues/1968
Feature requests
- Disable font ligatures (workaround: use a font without ligatures) https://github.com/blinksh/blink/issues/828
- Inverted ANSI prompt https://github.com/blinksh/blink/issues/1451
- EternalTerminal support https://github.com/blinksh/blink/issues/597
- Can’t use trackpad or mouse on external display without Stage Manager.
- Sixel graphics, but mosh does not intend to support it. https://github.com/blinksh/blink/issues/750 and https://github.com/mobile-shell/mosh/issues/1081