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
|
#!/hint/bash
if [[ $TERM == eterm* ]]; then
## Primatives for interacting with Emacs ###############################
# _emacs_run LISP
_emacs_run() {
emacsclient -a false -e "$*" 2>/dev/null
}
# _emacs_quote UNQUOTED_STRING
_emacs_quote() {
local str="$*"
str="${str//\\/\\\\}" # \ -> \\
str="${str//\"/\\\"}" # " -> \"
str="\"${str}\"" # wrap it in quotes
printf '%s' "$str"
}
# _emacs_unquote QUOTED_STRING
_emacs_unquote() {
local str="$*"
if [[ $str =~ ^\"(.*)\"$ ]]; then
str=${BASH_REMATCH[1]} # un-quote it
str="${str//\\\\/\\}" # \\ -> \
str="${str//\\\"/\"}" # \" -> "
fi
printf '%s' "$str"
}
## High-level tasks ####################################################
# Set the TRAMP directory for remote hosts (shell -> emacs)
_emacs_set_remote_dir() {
# Because (term-handle-ansi-terminal-messages) is run
# after each item is set, the user should be set
# before the hostname is set, otherwise it will set
# (default-directory) to an invalid TRAMP string.
#
# The hostname is compared to (system-name) to check
# if it is localhost. In Emacs 25, (system-name) is
# just gethostname(2), and in Bash 4.2, $HOSTNAME is
# also just gethostname(2).
#
# As an aside, Emacs and Bash deal with hostnames >
# 255 bytes differently. They both use 255 bytes for
# the initial call, but Bash won't retry with a bigger
# limit, but Emacs will. I don't care, because
# besides such long hostnames being uncommon, Linux's
# HOST_NAME_MAX on i686 and x86_64 is only 64, so it's
# actually impossible. IDK about other kernels or
# architectures.
printf '\eAnSiT%s %s\n' \
u "$USER" \
c "$PWD" \
h "$HOSTNAME"
}
# Set the shell's X11 display (emacs -> shell)
_emacs_set_shell_DISPLAY() {
export DISPLAY=$(_emacs_unquote "$(_emacs_run "(cdr (assoc 'display (frame-parameters)))")")
[[ $DISPLAY != nil ]] || unset DISPLAY
}
## Install the hooks ###################################################
export SELECTED_EDITOR='emacsclient'
export EDITOR=$SELECTED_EDITOR
export VISUAL=$SELECTED_EDITOR
export PAGER=cat
if _emacs_run '()' >/dev/null; then
PROMPT_COMMAND+='_emacs_set_shell_DISPLAY;'
fi
# Remember, the $() strips the trailing newline, so add it back in
PS1_EXTRA+='\[$(_emacs_set_remote_dir)'$'\n\\]'
fi
|