#!/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