This emacs module implements a bridge to libvterm to display a terminal in an Emacs buffer.
This is an alpha release, so it will crash your Emacs. If it does, please report a bug!
Clone the repository:
git clone https://github.com/akermu/emacs-libvterm.gitBefore installing emacs-libvterm, you need to make sure you have installed
- Emacs with module
support.
You can check that, by verifying that
module-file-suffixis notnil. - cmake (>=3.11)
- libtool-bin (related issues: #66 #85)
- If you compile vterm with
-DUSE_SYSTEM_LIBVTERMmake sure you have the library from https://github.com/neovim/libvterm
Run the build:
mkdir -p build
cd build
cmake ..
makeAnd add this to your init.el:
(add-to-list 'load-path "path/to/emacs-libvterm")
(require 'vterm)Or, with use-package:
(use-package vterm
:load-path "path/to/emacs-libvterm/"
)vterm is available on MELPA, and it can be installed as
a normal package. If the requirements are satisfied (mainly, Emacs was built
with support for modules), vterm will take care of the compilation of all its
components.
vterm can be install with MELPA with use-package by adding the following
lines to your init.el:
(use-package vterm
:ensure t
)If you have successfully built the module, you can test it by executing the
following command in the build directory:
make runOpen a terminal in the current window.
Open a terminal in another window.
When you enable vterm-copy-mode, the terminal buffer behaves like a normal
read-only text buffer: you can search, copy text, etc. The default keybinding
to toggle vterm-copy-mode is C-c C-t. When a region is selected, it is
possible to copy the text and leave vterm-copy-mode with the enter key.
vterm-clear-scrollback does exactly what the name suggests: it clears the
current buffer from the data that it is not currently visible.
vterm-clear-scrollback is bound to C-c C-l. This function is typically used
with the clear function provided by the shell to clear both screen and
scrollback. In order to achieve this behavior, you need to add a new shell alias.
For bash or zsh, put this in your .zshrc or .bashrc
function vterm_printf(){
if [ -n "$TMUX" ]; then
# tell tmux to pass the escape sequences through
# (Source: http://permalink.gmane.org/gmane.comp.terminal-emulators.tmux.user/1324)
printf "\ePtmux;\e\e]%s\007\e\\" "$1"
elif [ "${TERM%%-*}" = "screen" ]; then
# GNU screen (screen, screen-256color, screen-256color-bce)
printf "\eP\e]%s\007\e\\" "$1"
else
printf "\e]%s\e\\" "$1"
fi
}For fish put this in your ~/.config/fish/config.fish:
function vterm_printf;
if [ -n "$TMUX" ]
# tell tmux to pass the escape sequences through
# (Source: http://permalink.gmane.org/gmane.comp.terminal-emulators.tmux.user/1324)
printf "\ePtmux;\e\e]%s\007\e\\" "$argv"
else if string match -q -- "screen*" "$TERM"
# GNU screen (screen, screen-256color, screen-256color-bce)
printf "\eP\e]%s\007\e\\" "$argv"
else
printf "\e]%s\e\\" "$argv"
end
endFor zsh, put this in your .zshrc:
if [[ "$INSIDE_EMACS" = 'vterm' ]]; then
alias clear='vterm_printf "51;Evterm-clear-scrollback";tput clear'
fiFor bash, put this in your .bashrc:
if [[ "$INSIDE_EMACS" = 'vterm' ]]; then
function clear(){
vterm_printf "51;Evterm-clear-scrollback";
tput clear;
}
fiThese aliases take advantage of the fact that vterm can execute elisp
commands, as explained below.
Shell to run in a new vterm. It defaults to $SHELL.
Value for the TERM environment variable. It defaults to xterm-256color. If
eterm-256color is installed,
setting vterm-term-environment-variable to eterm-color improves the
rendering of colors in some systems.
If you want a key to be sent to the terminal, bind it to vterm--self-insert,
or remove it from vterm-mode-map. By default, vterm.el binds most of the
C-<char> and M-<char> keys, <f1> through <f12> and some special keys
like <backspace> and <return>. Sending a keyboard interrupt is bound to C-c C-c.
Set the :foreground and :background attributes of the following faces to a
color you like. The :foreground is ansi color 0-7, the :background attribute
is ansi color 8-15.
- vterm-color-default
- vterm-color-black
- vterm-color-red
- vterm-color-green
- vterm-color-yellow
- vterm-color-blue
- vterm-color-magenta
- vterm-color-cyan
- vterm-color-white
vterm supports directory tracking. If this feature is enabled, the default
directory in Emacs and the current working directory in vterm are synced. As a
result, interactive functions that ask for a path or a file (e.g., dired or
find-file) will do so starting from the current location.
Directory tracking requires some configuration, as the shell has to be instructed to share the relevant information with Emacs.
For zsh, put this at the end of your .zshrc:
vterm_prompt_end() {
vterm_printf "51;A$(whoami)@$(hostname):$(pwd)";
}
PROMPT=$PROMPT'%{$(vterm_prompt_end)%}'For bash, put this at the end of your .bashrc:
vterm_prompt_end(){
vterm_printf "51;A$(whoami)@$(hostname):$(pwd)"
}
PS1=$PS1'\[$(vterm_prompt_end)\]'For fish, put this in your ~/.config/fish/config.fish:
function fish_vterm_prompt_end;
vterm_printf '51;A'(whoami)'@'(hostname)':'(pwd)
end
function track_directories --on-event fish_prompt; fish_vterm_prompt_end; endDirectory tracking works on remote servers too. In case the hostname of your
remote machine does not match the actual hostname needed to connect to that
server, change $(hostname) with the correct one.
vterm can read and execute commands. At the moment, a command is
passed by providing a specific escape sequence. For example, to evaluate
(message "Hello!")use
printf "\e]51;Emessage \"Hello\!\"\e\\"
# or
vterm_printf "51;Emessage \"Hello\!\""The commands that are understood are defined in the setting vterm-eval-cmds.
As split-string-and-unquote is used the parse the passed string, double quotes
and backslashes need to be escaped via backslash. For instance, bash can replace
strings internally.
vterm_cmd() {
if [ -n "$TMUX" ]; then
# tell tmux to pass the escape sequences through
# (Source: http://permalink.gmane.org/gmane.comp.terminal-emulators.tmux.user/1324)
printf "\ePtmux;\e\e]51;E"
elif [ "${TERM%%-*}" = "screen" ]; then
# GNU screen (screen, screen-256color, screen-256color-bce)
printf "\eP\e]51;E"
else
printf "\e]51;E"
fi
printf "\e]51;E"
local r
while [[ $# -gt 0 ]]; do
r="${1//\\/\\\\}"
r="${r//\"/\\\"}"
printf '"%s" ' "$r"
shift
done
if [ -n "$TMUX" ]; then
# tell tmux to pass the escape sequences through
# (Source: http://permalink.gmane.org/gmane.comp.terminal-emulators.tmux.user/1324)
printf "\007\e\\"
elif [ "${TERM%%-*}" = "screen" ]; then
# GNU screen (screen, screen-256color, screen-256color-bce)
printf "\007\e\\"
else
printf "\e\\"
fi
}However if you are using dash and need a pure POSIX implementation:
vterm_cmd() {
if [ -n "$TMUX" ]; then
# tell tmux to pass the escape sequences through
# (Source: http://permalink.gmane.org/gmane.comp.terminal-emulators.tmux.user/1324)
printf "\ePtmux;\e\e]51;E"
elif [ "${TERM%%-*}" = "screen" ]; then
# GNU screen (screen, screen-256color, screen-256color-bce)
printf "\eP\e]51;E"
else
printf "\e]51;E"
fi
while [ $# -gt 0 ]; do
printf '"%s" ' "$(printf "%s" "$1" | sed -e 's|\\|\\\\|g' -e 's|"|\\"|g')"
shift
done
if [ -n "$TMUX" ]; then
# tell tmux to pass the escape sequences through
# (Source: http://permalink.gmane.org/gmane.comp.terminal-emulators.tmux.user/1324)
printf "\007\e\\"
elif [ "${TERM%%-*}" = "screen" ]; then
# GNU screen (screen, screen-256color, screen-256color-bce)
printf "\007\e\\"
else
printf "\e\\"
fi
}Now we can write shell functions to call the ones defined in vterm-eval-cmds.
find_file() {
vterm_cmd find-file "$(realpath "$@")"
}
say() {
vterm_cmd message "%s" "$*"
}This can be used inside vterm as
find_file name_of_file_in_local_directoryAs an example, say you like having files opened below the current window. You could add the command to do it on the lisp side like so:
(push (list "find-file-below"
(lambda (path)
(if-let* ((buf (find-file-noselect path))
(window (display-buffer-below-selected buf nil)))
(select-window window)
(message "Failed to open file: %s" path))))
vterm-eval-cmds)Then add the command in your .bashrc file.
open_file_below() {
vterm_cmd find-file-below "$(realpath "$@")"
}Then you can open any file from inside your shell.
open_file_below ~/Documents- vterm-toggle: Toggles between a vterm and the current buffer
- multi-libvterm: Multiterm for emacs-libvterm