pkg update and first config fix
org-brain not working, add org-roam
This commit is contained in:
@@ -42,6 +42,15 @@ if (USE_SYSTEM_LIBVTERM)
|
||||
# add_compile_definitions(VTermStringFragmentNotExists)
|
||||
add_definitions(-DVTermStringFragmentNotExists)
|
||||
endif()
|
||||
execute_process(COMMAND grep -c "VTermSelectionMask" "${LIBVTERM_INCLUDE_DIR}/vterm.h" OUTPUT_VARIABLE VTermSelectionMaskExists)
|
||||
if (${VTermSelectionMaskExists} EQUAL "0")
|
||||
# add_compile_definitions(VTermStringFragmentNotExists)
|
||||
add_definitions(-DVTermSelectionMaskNotExists)
|
||||
endif()
|
||||
execute_process(COMMAND grep -c "sb_clear" "${LIBVTERM_INCLUDE_DIR}/vterm.h" OUTPUT_VARIABLE VTermSBClearExists)
|
||||
if (${VTermSBClearExists} EQUAL "0")
|
||||
add_definitions(-DVTermSBClearNotExists)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "System libvterm not found: libvterm will be downloaded and compiled as part of the build process")
|
||||
endif()
|
||||
@@ -63,8 +72,8 @@ else()
|
||||
endif()
|
||||
|
||||
ExternalProject_add(libvterm
|
||||
GIT_REPOSITORY https://github.com/neovim/libvterm.git
|
||||
GIT_TAG 54c03b21f763fa775a4c0643a9d8326342873179
|
||||
GIT_REPOSITORY https://github.com/Sbozzolo/libvterm-mirror.git
|
||||
GIT_TAG 64f1775952dbe001e989f2ab679563b54f2fca55
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ${LIBVTERM_BUILD_COMMAND} "CFLAGS='-fPIC'"
|
||||
BUILD_IN_SOURCE ON
|
||||
|
||||
@@ -68,7 +68,7 @@ Before installing emacs-libvterm, you need to make sure you have installed
|
||||
3. libtool-bin (related issues:
|
||||
[#66](https://github.com/akermu/emacs-libvterm/issues/66)
|
||||
[#85](https://github.com/akermu/emacs-libvterm/issues/85#issuecomment-491845136))
|
||||
4. OPTIONAL: [libvterm](https://github.com/neovim/libvterm) (>= 0.1). This
|
||||
4. OPTIONAL: [libvterm](https://github.com/Sbozzolo/libvterm-mirror.git) (>= 0.2). This
|
||||
library can be found in the official repositories of most distributions
|
||||
(e.g., Arch, Debian, Fedora, Gentoo, openSUSE, Ubuntu). Typical names are
|
||||
`libvterm` (Arch, Fedora, Gentoo, openSUSE), or `libvterm-dev` (Debian,
|
||||
@@ -114,7 +114,7 @@ always want to use the vendored version as opposed to the one on you system, set
|
||||
|
||||
Build the module with:
|
||||
|
||||
``` sh
|
||||
```sh
|
||||
cd emacs-libvterm
|
||||
mkdir -p build
|
||||
cd build
|
||||
@@ -124,7 +124,7 @@ make
|
||||
|
||||
And add this to your `init.el`:
|
||||
|
||||
``` elisp
|
||||
```elisp
|
||||
(add-to-list 'load-path "path/to/emacs-libvterm")
|
||||
(require 'vterm)
|
||||
```
|
||||
@@ -153,23 +153,28 @@ There are a few options for installing Emacs27 on Ubuntu 20.04:
|
||||
In any case, if you have an older Emacs version you will need to purge it before proceeding:
|
||||
|
||||
#### Purge Emacs
|
||||
|
||||
```sh
|
||||
sudo apt --purge remove emacs
|
||||
sudo apt autoremove
|
||||
```
|
||||
|
||||
#### Installing Emacs27 from Kevin Kelley PPA
|
||||
|
||||
```sh
|
||||
sudo add-apt-repository ppa:kelleyk/emacs
|
||||
sudo apt install emacs27
|
||||
```
|
||||
|
||||
##### If you get an error about emacs27_common during the install process:
|
||||
|
||||
```sh
|
||||
Errors were encountered while processing:
|
||||
/tmp/apt-dpkg-install-RVK8CA/064-emacs27-common_27.1~1.git86d8d76aa3-kk2+20.04_all.deb
|
||||
```
|
||||
|
||||
run
|
||||
|
||||
```sh
|
||||
sudo apt --purge remove emacs-common
|
||||
sudo apt --fix-broken install
|
||||
@@ -177,12 +182,14 @@ sudo apt --fix-broken install
|
||||
|
||||
#### Installing Emacs27 from Snap
|
||||
I hesitate to include SNAP here, because I ran into a number of GTK Theme parsing errors, and Fontconfig errors when I tested it, and reverted to installing from Kevin Kelley's PPA. YMMV
|
||||
|
||||
```sh
|
||||
sudo snap install emacs --classic
|
||||
```
|
||||
|
||||
#### Install CMake and Libtool
|
||||
In Ubuntu 20.04 CMake (v3.16.3-1ubuntu1) and Libtool can be installed with
|
||||
|
||||
```sh
|
||||
sudo apt install cmake
|
||||
sudo apt install libtool
|
||||
@@ -200,6 +207,7 @@ The binary in Ubuntu Emacs Lisp PPA is currently broken and leads to segmentatio
|
||||
(see [#185](https://github.com/akermu/emacs-libvterm/issues/185#issuecomment-562237077)).
|
||||
In case Emacs is already on the system, you need to purge it before proceeding
|
||||
with the following commands.
|
||||
|
||||
```sh
|
||||
sudo add-apt-repository ppa:kelleyk/emacs
|
||||
sudo apt update
|
||||
@@ -207,6 +215,7 @@ sudo apt-get install emacs26
|
||||
```
|
||||
|
||||
A way to install a recent version of CMake (>= 3.11) is with linuxbrew.
|
||||
|
||||
```sh
|
||||
brew install cmake
|
||||
```
|
||||
@@ -240,9 +249,10 @@ via properly escaped sequences. A function that helps in this task,
|
||||
readme.
|
||||
|
||||
For `bash` or `zsh`, put this in your `.zshrc` or `.bashrc`
|
||||
```bash
|
||||
vterm_printf(){
|
||||
if [ -n "$TMUX" ] && ([ "${TERM%%-*}" = "tmux" ] || [ "${TERM%%-*}" = "screen" ] ); then
|
||||
|
||||
```sh
|
||||
vterm_printf() {
|
||||
if [ -n "$TMUX" ] && ([ "${TERM%%-*}" = "tmux" ] || [ "${TERM%%-*}" = "screen" ]); then
|
||||
# Tell tmux to pass the escape sequences through
|
||||
printf "\ePtmux;\e\e]%s\007\e\\" "$1"
|
||||
elif [ "${TERM%%-*}" = "screen" ]; then
|
||||
@@ -253,10 +263,12 @@ vterm_printf(){
|
||||
fi
|
||||
}
|
||||
```
|
||||
|
||||
This works also for `dash`.
|
||||
|
||||
For `fish` put this in your `~/.config/fish/config.fish`:
|
||||
```bash
|
||||
|
||||
```fish
|
||||
function vterm_printf;
|
||||
if begin; [ -n "$TMUX" ] ; and string match -q -r "screen|tmux" "$TERM"; end
|
||||
# tell tmux to pass the escape sequences through
|
||||
@@ -309,23 +321,27 @@ 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 `zsh`, put this in your `.zshrc`:
|
||||
```zsh
|
||||
|
||||
```zsh
|
||||
if [[ "$INSIDE_EMACS" = 'vterm' ]]; then
|
||||
alias clear='vterm_printf "51;Evterm-clear-scrollback";tput clear'
|
||||
fi
|
||||
```
|
||||
|
||||
For `bash`, put this in your `.bashrc`:
|
||||
|
||||
```bash
|
||||
if [[ "$INSIDE_EMACS" = 'vterm' ]]; then
|
||||
function clear(){
|
||||
function clear() {
|
||||
vterm_printf "51;Evterm-clear-scrollback";
|
||||
tput clear;
|
||||
}
|
||||
fi
|
||||
```
|
||||
|
||||
For `fish`:
|
||||
```
|
||||
|
||||
```fish
|
||||
if [ "$INSIDE_EMACS" = 'vterm' ]
|
||||
function clear
|
||||
vterm_printf "51;Evterm-clear-scrollback";
|
||||
@@ -333,6 +349,7 @@ if [ "$INSIDE_EMACS" = 'vterm' ]
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
These aliases take advantage of the fact that `vterm` can execute `elisp`
|
||||
commands, as explained below.
|
||||
|
||||
@@ -420,23 +437,29 @@ to which all the vterm buffers will be named "vterm TITLE".
|
||||
This requires some shell-side configuration to print the title. For example to
|
||||
set the name "HOSTNAME:PWD", use can you the following:
|
||||
|
||||
For `zsh`
|
||||
For `zsh`,
|
||||
|
||||
```zsh
|
||||
autoload -U add-zsh-hook
|
||||
add-zsh-hook -Uz chpwd (){ print -Pn "\e]2;%m:%2~\a" }
|
||||
```
|
||||
|
||||
For `bash`,
|
||||
|
||||
```bash
|
||||
PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND; }"'echo -ne "\033]0;${HOSTNAME}:${PWD}\007"'
|
||||
```
|
||||
|
||||
For `fish`,
|
||||
|
||||
```fish
|
||||
function fish_title
|
||||
hostname
|
||||
echo ":"
|
||||
pwd
|
||||
prompt_pwd
|
||||
end
|
||||
```
|
||||
|
||||
See [zsh and bash](http://tldp.org/HOWTO/Xterm-Title-4.html) and [fish
|
||||
documentations](https://fishshell.com/docs/current/#programmable-title).
|
||||
|
||||
@@ -455,11 +478,23 @@ or remove it from `vterm-mode-map`. By default, `vterm.el` binds most of the
|
||||
like `<backspace>` and `<return>`. Sending a keyboard interrupt is bound to `C-c
|
||||
C-c`.
|
||||
|
||||
In order to send a keypress that is already recognized by Emacs, such as `C-g`,
|
||||
use the interactive function `vterm-send-next-key`. This can be bound to a key
|
||||
in the `vterm-mode-map` like `C-q`, in which case pressing `C-q C-g` will send a
|
||||
`C-g` key to the terminal, and so on for other modified keys:
|
||||
|
||||
```elisp
|
||||
(define-key vterm-mode-map (kbd "C-q") #'vterm-send-next-key)
|
||||
```
|
||||
|
||||
This can be useful for controlling an application running in the terminal, such
|
||||
as Emacs or Nano.
|
||||
|
||||
## Fonts
|
||||
|
||||
You can change the font (the _face_) used in a vterm with the following code:
|
||||
|
||||
``` emacs
|
||||
```elisp
|
||||
(add-hook 'vterm-mode-hook
|
||||
(lambda ()
|
||||
(set (make-local-variable 'buffer-face-mode-face) 'fixed-pitch)
|
||||
@@ -525,7 +560,7 @@ For `zsh`, put this at the end of your `.zshrc`:
|
||||
|
||||
```zsh
|
||||
vterm_prompt_end() {
|
||||
vterm_printf "51;A$(whoami)@$(hostname):$(pwd)";
|
||||
vterm_printf "51;A$(whoami)@$(hostname):$(pwd)"
|
||||
}
|
||||
setopt PROMPT_SUBST
|
||||
PROMPT=$PROMPT'%{$(vterm_prompt_end)%}'
|
||||
@@ -555,14 +590,15 @@ function fish_prompt --description 'Write out the prompt; do not replace this. I
|
||||
vterm_prompt_end
|
||||
end
|
||||
```
|
||||
|
||||
Here we are using the function `vterm_printf` that we have discussed above, so make
|
||||
sure that this function is defined in your configuration file.
|
||||
|
||||
|
||||
Directory 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. For example, if the correct
|
||||
hostname is `foo` and the username is `bar`, you should have something like
|
||||
|
||||
```bash
|
||||
HOSTNAME=foo
|
||||
USER=baz
|
||||
@@ -573,11 +609,14 @@ vterm_printf "51;A$USER@$HOSTNAME:$(pwd)"
|
||||
|
||||
`vterm` can read and execute commands. At the moment, a command is
|
||||
passed by providing a specific escape sequence. For example, to evaluate
|
||||
``` elisp
|
||||
|
||||
```elisp
|
||||
(message "Hello!")
|
||||
```
|
||||
|
||||
use
|
||||
``` sh
|
||||
|
||||
```sh
|
||||
printf "\e]51;Emessage \"Hello\!\"\e\\"
|
||||
# or
|
||||
vterm_printf "51;Emessage \"Hello\!\""
|
||||
@@ -590,6 +629,7 @@ and backslashes need to be escaped via backslash. A convenient shell function to
|
||||
automate the substitution is
|
||||
|
||||
`bash` or `zsh`:
|
||||
|
||||
```sh
|
||||
vterm_cmd() {
|
||||
local vterm_elisp
|
||||
@@ -601,8 +641,10 @@ vterm_cmd() {
|
||||
vterm_printf "51;E$vterm_elisp"
|
||||
}
|
||||
```
|
||||
|
||||
`fish`:
|
||||
```sh
|
||||
|
||||
```fish
|
||||
function vterm_cmd --description 'Run an Emacs command among the ones been defined in vterm-eval-cmds.'
|
||||
set -l vterm_elisp ()
|
||||
for arg in $argv
|
||||
@@ -625,6 +667,7 @@ say() {
|
||||
```
|
||||
|
||||
Or for `fish`:
|
||||
|
||||
```fish
|
||||
function find_file
|
||||
set -q argv[1]; or set argv[1] "."
|
||||
@@ -641,13 +684,14 @@ This newly defined `find_file` function can now be used inside `vterm` as
|
||||
```sh
|
||||
find_file name_of_file_in_local_directory
|
||||
```
|
||||
|
||||
If you call `find_file` without specifying any file (you just execute `find_file` in your shell),
|
||||
`dired` will open with the current directory.
|
||||
|
||||
As 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:
|
||||
|
||||
``` elisp
|
||||
```elisp
|
||||
(push (list "find-file-below"
|
||||
(lambda (path)
|
||||
(if-let* ((buf (find-file-noselect path))
|
||||
@@ -688,7 +732,7 @@ in the EMACS_VTERM_PATH inside the /etc sub-directory. After a package update, t
|
||||
so, a code like this in your bashrc could be enough to load always the latest version of the file
|
||||
from the right location without coping any file manually.
|
||||
|
||||
```
|
||||
```sh
|
||||
if [[ "$INSIDE_EMACS" = 'vterm' ]] \
|
||||
&& [[ -n ${EMACS_VTERM_PATH} ]] \
|
||||
&& [[ -f ${EMACS_VTERM_PATH}/etc/emacs-vterm-bash.sh ]]; then
|
||||
@@ -718,16 +762,19 @@ The version of `libvterm` installed on your system is too old. You should let
|
||||
`emacs-libvterm` download `libvterm` for you. You can either uninstall your
|
||||
libvterm, or instruct Emacs to ignore the system libvterm. If you are compiling
|
||||
from Emacs, you can do this by setting:
|
||||
```emacs-lisp
|
||||
|
||||
```elisp
|
||||
(setq vterm-module-cmake-args "-DUSE_SYSTEM_LIBVTERM=no")
|
||||
```
|
||||
|
||||
and compile again. If you are compiling with CMake, use the flag
|
||||
`-DUSE_SYSTEM_LIBVTERM=no`.
|
||||
|
||||
### `<C-backspace>` doesn't kill previous word.
|
||||
|
||||
This can be fixed by rebinding the key to what `C-w` does:
|
||||
```emacs-lisp
|
||||
|
||||
```elisp
|
||||
(define-key vterm-mode-map (kbd "<C-backspace>")
|
||||
(lambda () (interactive) (vterm-send-key (kbd "C-w"))))
|
||||
```
|
||||
@@ -736,7 +783,8 @@ This can be fixed by rebinding the key to what `C-w` does:
|
||||
|
||||
Add this piece of code to your configuration file to make `counsel` use
|
||||
the correct function to yank in vterm buffers.
|
||||
```emacs-lisp
|
||||
|
||||
```elisp
|
||||
(defun vterm-counsel-yank-pop-action (orig-fun &rest args)
|
||||
(if (equal major-mode 'vterm-mode)
|
||||
(let ((inhibit-read-only t)
|
||||
@@ -755,7 +803,8 @@ We recommend that you set up shell-side configuration for reliable directory
|
||||
tracking. If you cannot do it, a possible workaround is the following.
|
||||
|
||||
On most GNU/Linux systems, you can read current directory from `/proc`:
|
||||
```emacs-lisp
|
||||
|
||||
```elisp
|
||||
(defun vterm-directory-sync ()
|
||||
"Synchronize current working directory."
|
||||
(interactive)
|
||||
@@ -764,10 +813,13 @@ On most GNU/Linux systems, you can read current directory from `/proc`:
|
||||
(dir (file-truename (format "/proc/%d/cwd/" pid))))
|
||||
(setq default-directory dir))))
|
||||
```
|
||||
|
||||
A possible application of this function is in combination with `find-file`:
|
||||
```emacs-lisp
|
||||
|
||||
```elisp
|
||||
(advice-add #'find-file :before #'vterm-directory-sync)
|
||||
```
|
||||
|
||||
This method does not work on remote machines.
|
||||
|
||||
### How can I get the directory tracking in a more understandable way?
|
||||
@@ -779,32 +831,37 @@ are using `fish`).
|
||||
There is another way to achieve this behavior. Define a shell function, on a
|
||||
local host you can simply use
|
||||
|
||||
``` sh
|
||||
```sh
|
||||
vterm_set_directory() {
|
||||
vterm_cmd update-pwd "$PWD/"
|
||||
}
|
||||
```
|
||||
|
||||
On a remote one, use instead
|
||||
``` sh
|
||||
|
||||
```sh
|
||||
vterm_set_directory() {
|
||||
vterm_cmd update-pwd "/-:""$USER""@""$HOSTNAME"":""$PWD/"
|
||||
}
|
||||
```
|
||||
|
||||
Then, for `zsh`, add this function to the `chpwd` hook:
|
||||
|
||||
``` sh
|
||||
```zsh
|
||||
autoload -U add-zsh-hook
|
||||
add-zsh-hook -Uz chpwd (){ vterm_set_directory }
|
||||
```
|
||||
|
||||
For `bash`, append it to the prompt:
|
||||
|
||||
``` sh
|
||||
```bash
|
||||
PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND; }vterm_set_directory"
|
||||
```
|
||||
|
||||
Finally, add `update-pwd` to the list of commands that Emacs
|
||||
is allowed to execute from vterm:
|
||||
|
||||
``` emacs-lisp
|
||||
```elisp
|
||||
(add-to-list 'vterm-eval-cmds '("update-pwd" (lambda (path) (setq default-directory path))))
|
||||
```
|
||||
|
||||
@@ -813,7 +870,7 @@ is allowed to execute from vterm:
|
||||
`evil-collection` provides a solution for this problem. If you do not want to
|
||||
use `evil-collection`, you can add the following code:
|
||||
|
||||
```emacs-lisp
|
||||
```elisp
|
||||
(defun evil-collection-vterm-escape-stay ()
|
||||
"Go back to normal state but don't move
|
||||
cursor backwards. Moving cursor backwards is the default vim behavior but it is
|
||||
@@ -836,6 +893,12 @@ not appropriate in some cases like terminals."
|
||||
|
||||
Obsolete variables will be removed in version 0.1.
|
||||
|
||||
#### August 2022
|
||||
* `vterm-send-C-[a-z]` `vterm-send-M-[a-z]` `vterm-define-key`
|
||||
`vterm-send-{up/down/left/right/prior/next/meta-dot/meta-comma/ctrl-slash}`
|
||||
were obsolete, please use `vterm-send` or `vterm-send-key` or
|
||||
`vterm--self-insert` instead.
|
||||
|
||||
#### October 2020
|
||||
|
||||
* `vterm-disable-bold-font` was renamed to `vterm-disable-bold` to uniform it
|
||||
|
||||
@@ -55,7 +55,7 @@ emacs_value Fvterm_invalidate;
|
||||
emacs_value Feq;
|
||||
emacs_value Fvterm_get_color;
|
||||
emacs_value Fvterm_eval;
|
||||
emacs_value Fvterm_selection;
|
||||
emacs_value Fvterm_set_selection;
|
||||
|
||||
/* Set the function cell of the symbol named NAME to SFUN using
|
||||
the 'fset' function. */
|
||||
@@ -202,8 +202,8 @@ emacs_value vterm_eval(emacs_env *env, emacs_value string) {
|
||||
return env->funcall(env, Fvterm_eval, 1, (emacs_value[]){string});
|
||||
}
|
||||
|
||||
emacs_value vterm_selection(emacs_env *env, emacs_value selection_target,
|
||||
emacs_value selection_data) {
|
||||
return env->funcall(env, Fvterm_selection, 2,
|
||||
emacs_value vterm_set_selection(emacs_env *env, emacs_value selection_target,
|
||||
emacs_value selection_data) {
|
||||
return env->funcall(env, Fvterm_set_selection, 2,
|
||||
(emacs_value[]){selection_target, selection_data});
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ extern emacs_value Fvterm_invalidate;
|
||||
extern emacs_value Feq;
|
||||
extern emacs_value Fvterm_get_color;
|
||||
extern emacs_value Fvterm_eval;
|
||||
extern emacs_value Fvterm_selection;
|
||||
extern emacs_value Fvterm_set_selection;
|
||||
|
||||
// Utils
|
||||
void bind_function(emacs_env *env, const char *name, emacs_value Sfun);
|
||||
@@ -93,7 +93,7 @@ void set_directory(emacs_env *env, emacs_value string);
|
||||
void vterm_invalidate(emacs_env *env);
|
||||
emacs_value vterm_get_color(emacs_env *env, int index);
|
||||
emacs_value vterm_eval(emacs_env *env, emacs_value string);
|
||||
emacs_value vterm_selection(emacs_env *env, emacs_value selection_target,
|
||||
emacs_value selection_data);
|
||||
emacs_value vterm_set_selection(emacs_env *env, emacs_value selection_target,
|
||||
emacs_value selection_data);
|
||||
|
||||
#endif /* ELISP_H */
|
||||
|
||||
@@ -48,7 +48,7 @@ add-zsh-hook -Uz chpwd (){ print -Pn "\e]2;%m:%2~\a" }
|
||||
# The escape sequence "51;A" has also the role of identifying the end of the
|
||||
# prompt
|
||||
vterm_prompt_end() {
|
||||
vterm_printf "51;A$(whoami)@$(hostname):$(pwd)";
|
||||
vterm_printf "51;A$(whoami)@$(hostname):$(pwd)"
|
||||
}
|
||||
setopt PROMPT_SUBST
|
||||
PROMPT=$PROMPT'%{$(vterm_prompt_end)%}'
|
||||
|
||||
@@ -30,7 +30,7 @@ end
|
||||
function fish_title
|
||||
hostname
|
||||
echo ":"
|
||||
pwd
|
||||
prompt_pwd
|
||||
end
|
||||
|
||||
# With vterm_cmd you can execute Emacs commands directly from the shell.
|
||||
|
||||
@@ -154,6 +154,32 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int term_sb_clear(void *data) {
|
||||
Term *term = (Term *)data;
|
||||
|
||||
if (term->sb_clear_pending) {
|
||||
// Another scrollback clear is already pending, so skip this one.
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < term->sb_current; i++) {
|
||||
if (term->sb_buffer[i]->info != NULL) {
|
||||
free_lineinfo(term->sb_buffer[i]->info);
|
||||
term->sb_buffer[i]->info = NULL;
|
||||
}
|
||||
free(term->sb_buffer[i]);
|
||||
}
|
||||
free(term->sb_buffer);
|
||||
term->sb_buffer = malloc(sizeof(ScrollbackLine *) * term->sb_size);
|
||||
term->sb_clear_pending = true;
|
||||
term->sb_current = 0;
|
||||
term->sb_pending = 0;
|
||||
term->sb_pending_by_height_decr = 0;
|
||||
invalidate_terminal(term, -1, -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int row_to_linenr(Term *term, int row) {
|
||||
return row != INT_MAX ? row + (int)term->sb_current + 1 : INT_MAX;
|
||||
}
|
||||
@@ -436,6 +462,14 @@ static int term_resize(int rows, int cols, void *user_data) {
|
||||
static void refresh_scrollback(Term *term, emacs_env *env) {
|
||||
int max_line_count = (int)term->sb_current + term->height;
|
||||
int del_cnt = 0;
|
||||
if (term->sb_clear_pending) {
|
||||
del_cnt = term->linenum - term->height;
|
||||
if (del_cnt > 0) {
|
||||
delete_lines(env, 1, del_cnt, true);
|
||||
term->linenum -= del_cnt;
|
||||
}
|
||||
term->sb_clear_pending = false;
|
||||
}
|
||||
if (term->sb_pending > 0) {
|
||||
// This means that either the window height has decreased or the screen
|
||||
// became full and libvterm had to push all rows up. Convert the first
|
||||
@@ -608,13 +642,13 @@ static void term_redraw(Term *term, emacs_env *env) {
|
||||
term->elisp_code_p_insert = &term->elisp_code_first;
|
||||
|
||||
if (term->selection_data) {
|
||||
emacs_value selection_target = env->make_string(
|
||||
env, &term->selection_target[0], strlen(&term->selection_target[0]));
|
||||
emacs_value selection_mask = env->make_integer(env, term->selection_mask);
|
||||
emacs_value selection_data = env->make_string(env, term->selection_data,
|
||||
strlen(term->selection_data));
|
||||
vterm_selection(env, selection_target, selection_data);
|
||||
vterm_set_selection(env, selection_mask, selection_data);
|
||||
free(term->selection_data);
|
||||
term->selection_data = NULL;
|
||||
term->selection_mask = 0;
|
||||
}
|
||||
|
||||
term->is_invalidated = false;
|
||||
@@ -628,6 +662,9 @@ static VTermScreenCallbacks vterm_screen_callbacks = {
|
||||
.resize = term_resize,
|
||||
.sb_pushline = term_sb_push,
|
||||
.sb_popline = term_sb_pop,
|
||||
#if !defined(VTermSBClearNotExists)
|
||||
.sb_clear = term_sb_clear,
|
||||
#endif
|
||||
};
|
||||
|
||||
static bool compare_cells(VTermScreenCell *a, VTermScreenCell *b) {
|
||||
@@ -846,24 +883,11 @@ static void term_flush_output(Term *term, emacs_env *env) {
|
||||
}
|
||||
|
||||
static void term_clear_scrollback(Term *term, emacs_env *env) {
|
||||
term_sb_clear(term);
|
||||
vterm_screen_flush_damage(term->vts);
|
||||
term_redraw(term, env);
|
||||
if (term->sb_pending > 0) { // Pending rows must be processed first.
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < term->sb_current; i++) {
|
||||
if (term->sb_buffer[i]->info != NULL) {
|
||||
free_lineinfo(term->sb_buffer[i]->info);
|
||||
term->sb_buffer[i]->info = NULL;
|
||||
}
|
||||
free(term->sb_buffer[i]);
|
||||
}
|
||||
free(term->sb_buffer);
|
||||
term->sb_buffer = malloc(sizeof(ScrollbackLine *) * term->sb_size);
|
||||
delete_lines(env, 1, term->sb_current, true);
|
||||
term->linenum -= term->sb_current;
|
||||
term->sb_current = 0;
|
||||
}
|
||||
|
||||
static void term_process_key(Term *term, emacs_env *env, unsigned char *key,
|
||||
size_t len, VTermModifier modifier) {
|
||||
if (is_key(key, len, "<clear_scrollback>")) {
|
||||
@@ -1076,37 +1100,7 @@ static int handle_osc_cmd_51(Term *term, char subCmd, char *buffer) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int handle_osc_cmd_52(Term *term, char *buffer) {
|
||||
/* OSC 52 ; Pc ; Pd BEL */
|
||||
/* Manipulate Selection Data */
|
||||
/* https://invisible-island.net/xterm/ctlseqs/ctlseqs.html */
|
||||
/* test by printf "\033]52;c;$(printf "%s" "blabla" | base64)\a" */
|
||||
|
||||
for (int i = 0; i < SELECTION_TARGET_MAX; i++) { /* reset Pc */
|
||||
term->selection_target[i] = 0;
|
||||
}
|
||||
int selection_target_idx = 0;
|
||||
size_t cmdlen = strlen(buffer);
|
||||
|
||||
for (int i = 0; i < cmdlen; i++) {
|
||||
/* OSC 52 ; Pc ; Pd BEL */
|
||||
if (buffer[i] == ';') { /* find the second ";" */
|
||||
term->selection_data = malloc(cmdlen - i);
|
||||
strcpy(term->selection_data, &buffer[i + 1]);
|
||||
break;
|
||||
}
|
||||
if (selection_target_idx < SELECTION_TARGET_MAX) {
|
||||
/* c , p , q , s , 0 , 1 , 2 , 3 , 4 , 5 , 6 , and 7 */
|
||||
/* for clipboard, primary, secondary, select, or cut buffers 0 through 7
|
||||
* respectively */
|
||||
term->selection_target[selection_target_idx] = buffer[i];
|
||||
selection_target_idx++;
|
||||
} else { /* len of Pc should not >12 just ignore this cmd,am I wrong? */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static int handle_osc_cmd(Term *term, int cmd, char *buffer) {
|
||||
if (cmd == 51) {
|
||||
char subCmd = '0';
|
||||
@@ -1116,11 +1110,11 @@ static int handle_osc_cmd(Term *term, int cmd, char *buffer) {
|
||||
subCmd = buffer[0];
|
||||
/* ++ skip the subcmd char */
|
||||
return handle_osc_cmd_51(term, subCmd, ++buffer);
|
||||
} else if (cmd == 52) {
|
||||
return handle_osc_cmd_52(term, buffer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* maybe we should drop support of libvterm < v0.2 */
|
||||
/* VTermStringFragmentNotExists was introduced when libvterm is not released */
|
||||
#ifdef VTermStringFragmentNotExists
|
||||
static int osc_callback(const char *command, size_t cmdlen, void *user) {
|
||||
Term *term = (Term *)user;
|
||||
@@ -1134,10 +1128,6 @@ static int osc_callback(const char *command, size_t cmdlen, void *user) {
|
||||
} else if (cmdlen > 4 && buffer[0] == '5' && buffer[1] == '1' &&
|
||||
buffer[2] == ';' && buffer[3] == 'E') {
|
||||
return handle_osc_cmd_51(term, 'E', &buffer[4]);
|
||||
} else if (cmdlen > 4 && buffer[0] == '5' && buffer[1] == '2' &&
|
||||
buffer[2] == ';') {
|
||||
/* OSC 52 ; Pc ; Pd BEL */
|
||||
return handle_osc_cmd_52(term, &buffer[3]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1159,13 +1149,6 @@ static int osc_callback(int cmd, VTermStringFragment frag, void *user) {
|
||||
/* "51;A" has also the role of identifying the end of the prompt */
|
||||
/* "51;E" executes elisp code */
|
||||
/* The elisp code is executed in term_redraw */
|
||||
|
||||
/* "52;[cpqs01234567];data" Manipulate Selection Data */
|
||||
/* I think libvterm has bug ,sometimes when the data is long enough ,the final
|
||||
* fragment is missed */
|
||||
/* printf "\033]52;c;$(printf "%s" $(ruby -e 'print "x"*999999')|base64)\a"
|
||||
*/
|
||||
|
||||
Term *term = (Term *)user;
|
||||
|
||||
if (frag.initial) {
|
||||
@@ -1194,6 +1177,37 @@ static VTermStateFallbacks parser_callbacks = {
|
||||
.osc = &osc_callback,
|
||||
.dcs = NULL,
|
||||
};
|
||||
#ifndef VTermSelectionMaskNotExists
|
||||
static int set_selection(VTermSelectionMask mask, VTermStringFragment frag,
|
||||
void *user) {
|
||||
Term *term = (Term *)user;
|
||||
|
||||
if (frag.initial) {
|
||||
term->selection_mask = mask;
|
||||
if (term->selection_data) {
|
||||
free(term->selection_data);
|
||||
}
|
||||
term->selection_data = NULL;
|
||||
}
|
||||
|
||||
if (frag.len) {
|
||||
term->selection_data =
|
||||
concat(term->selection_data, frag.str, frag.len, true);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* OSC 52 ; Pc ; Pd BEL */
|
||||
/* Manipulate Selection Data */
|
||||
/* https://invisible-island.net/xterm/ctlseqs/ctlseqs.html */
|
||||
/* test by printf "\033]52;c;$(printf "%s" "blabla" | base64)\a" */
|
||||
/* c , p , q , s , 0 , 1 , 2 , 3 , 4 , 5 , 6 , and 7 */
|
||||
/* for clipboard, primary, secondary, select, or cut buffers 0 through 7 */
|
||||
/* respectively */
|
||||
static VTermSelectionCallbacks selection_callbacks = {
|
||||
.set = &set_selection,
|
||||
.query = NULL,
|
||||
};
|
||||
#endif /* VTermSelectionMaskNotExists */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1217,6 +1231,11 @@ emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[],
|
||||
|
||||
VTermState *state = vterm_obtain_state(term->vt);
|
||||
vterm_state_set_unrecognised_fallbacks(state, &parser_callbacks, term);
|
||||
|
||||
#ifndef VTermSelectionMaskNotExists
|
||||
vterm_state_set_selection_callbacks(state, &selection_callbacks, term,
|
||||
term->selection_buf, SELECTION_BUF_LEN);
|
||||
#endif
|
||||
vterm_state_set_bold_highbright(state, set_bold_hightbright);
|
||||
|
||||
vterm_screen_reset(term->vts, 1);
|
||||
@@ -1226,6 +1245,7 @@ emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[],
|
||||
term->sb_size = MIN(SB_MAX, sb_size);
|
||||
term->sb_current = 0;
|
||||
term->sb_pending = 0;
|
||||
term->sb_clear_pending = false;
|
||||
term->sb_pending_by_height_decr = 0;
|
||||
term->sb_buffer = malloc(sizeof(ScrollbackLine *) * term->sb_size);
|
||||
term->invalid_start = 0;
|
||||
@@ -1262,6 +1282,7 @@ emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[],
|
||||
term->elisp_code_first = NULL;
|
||||
term->elisp_code_p_insert = &term->elisp_code_first;
|
||||
term->selection_data = NULL;
|
||||
term->selection_mask = 0;
|
||||
|
||||
term->cmd_buffer = NULL;
|
||||
|
||||
@@ -1472,8 +1493,8 @@ int emacs_module_init(struct emacs_runtime *ert) {
|
||||
Fvterm_get_color =
|
||||
env->make_global_ref(env, env->intern(env, "vterm--get-color"));
|
||||
Fvterm_eval = env->make_global_ref(env, env->intern(env, "vterm--eval"));
|
||||
Fvterm_selection =
|
||||
env->make_global_ref(env, env->intern(env, "vterm--selection"));
|
||||
Fvterm_set_selection =
|
||||
env->make_global_ref(env, env->intern(env, "vterm--set-selection"));
|
||||
|
||||
// Exported functions
|
||||
emacs_value fun;
|
||||
|
||||
@@ -8,17 +8,17 @@
|
||||
|
||||
// https://gcc.gnu.org/wiki/Visibility
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#ifdef __GNUC__
|
||||
#define VTERM_EXPORT __attribute__ ((dllexport))
|
||||
#else
|
||||
#define VTERM_EXPORT __declspec(dllexport)
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
#define VTERM_EXPORT __attribute__((dllexport))
|
||||
#else
|
||||
#if __GNUC__ >= 4
|
||||
#define VTERM_EXPORT __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define VTERM_EXPORT
|
||||
#endif
|
||||
#define VTERM_EXPORT __declspec(dllexport)
|
||||
#endif
|
||||
#else
|
||||
#if __GNUC__ >= 4
|
||||
#define VTERM_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define VTERM_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
VTERM_EXPORT int plugin_is_GPL_compatible;
|
||||
@@ -53,7 +53,7 @@ typedef struct ElispCodeListNode {
|
||||
|
||||
/* c , p , q , s , 0 , 1 , 2 , 3 , 4 , 5 , 6 , and 7 */
|
||||
/* clipboard, primary, secondary, select, or cut buffers 0 through 7 */
|
||||
#define SELECTION_TARGET_MAX 12
|
||||
#define SELECTION_BUF_LEN 4096
|
||||
|
||||
typedef struct Cursor {
|
||||
int row, col;
|
||||
@@ -79,6 +79,7 @@ typedef struct Term {
|
||||
// window height has increased) and must be deleted from the terminal buffer
|
||||
int sb_pending;
|
||||
int sb_pending_by_height_decr;
|
||||
bool sb_clear_pending;
|
||||
long linenum;
|
||||
long linenum_added;
|
||||
|
||||
@@ -100,8 +101,9 @@ typedef struct Term {
|
||||
|
||||
/* c , p , q , s , 0 , 1 , 2 , 3 , 4 , 5 , 6 , and 7 */
|
||||
/* clipboard, primary, secondary, select, or cut buffers 0 through 7 */
|
||||
char selection_target[SELECTION_TARGET_MAX];
|
||||
int selection_mask; /* see VTermSelectionMask in vterm.h */
|
||||
char *selection_data;
|
||||
char selection_buf[SELECTION_BUF_LEN];
|
||||
|
||||
/* the size of dirs almost = window height, value = directory of that line */
|
||||
LineInfo **lines;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(define-package "vterm" "20211226.817" "Fully-featured terminal emulator"
|
||||
(define-package "vterm" "20221118.1354" "Fully-featured terminal emulator"
|
||||
'((emacs "25.1"))
|
||||
:commit "a940dd2ee8a82684860e320c0f6d5e15d31d916f" :authors
|
||||
:commit "f14d113ee4618f052879509ec378feb9766b871b" :authors
|
||||
'(("Lukas Fürmetz" . "fuermetz@mailbox.org"))
|
||||
:maintainer
|
||||
'("Lukas Fürmetz" . "fuermetz@mailbox.org")
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
;; Copyright (C) 2017-2020 by Lukas Fürmetz & Contributors
|
||||
;;
|
||||
;; Author: Lukas Fürmetz <fuermetz@mailbox.org>
|
||||
;; Version: 0.0.1
|
||||
;; Version: 0.0.2
|
||||
;; URL: https://github.com/akermu/emacs-libvterm
|
||||
;; Keywords: terminals
|
||||
;; Package-Requires: ((emacs "25.1"))
|
||||
@@ -62,6 +62,8 @@
|
||||
(error "VTerm needs module support. Please compile Emacs with
|
||||
the --with-modules option!"))
|
||||
|
||||
(defvar vterm-copy-mode)
|
||||
|
||||
;;; Compilation of the module
|
||||
|
||||
(defcustom vterm-module-cmake-args ""
|
||||
@@ -191,7 +193,7 @@ named \"*vterm*<2>\"."
|
||||
:group 'vterm)
|
||||
|
||||
(defcustom vterm-max-scrollback 1000
|
||||
"Maximum 'scrollback' value.
|
||||
"Maximum \\='scrollback\\=' value.
|
||||
|
||||
The maximum allowed is 100000. This value can modified by
|
||||
changing the SB_MAX variable in vterm-module.h and recompiling
|
||||
@@ -229,7 +231,7 @@ screen in vterm buffers.
|
||||
If `vterm-clear-scrollback-when-clearing' is nil, `vterm-clear'
|
||||
clears only the screen, so the scrollback is accessible moving
|
||||
the point up."
|
||||
:type 'number
|
||||
:type 'boolean
|
||||
:group 'vterm)
|
||||
|
||||
(defcustom vterm-keymap-exceptions
|
||||
@@ -297,21 +299,21 @@ information on the how to configure the shell."
|
||||
(defcustom vterm-environment nil
|
||||
"List of extra environment variables to the vterm shell processes only.
|
||||
|
||||
demo: '(\"env1=v1\" \"env2=v2\")"
|
||||
demo: \\='(\"env1=v1\" \"env2=v2\")"
|
||||
:type '(repeat string)
|
||||
:group 'vterm)
|
||||
|
||||
|
||||
(defcustom vterm-enable-manipulate-selection-data-by-osc52 nil
|
||||
"Support OSC 52 MANIPULATE SELECTION DATA.
|
||||
"Support OSC 52 MANIPULATE SELECTION DATA(libvterm 0.2 is needed).
|
||||
|
||||
Support copy text to emacs kill ring and system clipboard by using OSC 52.
|
||||
For example: send base64 encoded 'foo' to kill ring: echo -en '\e]52;c;Zm9v\a',
|
||||
Support copy text to Emacs kill ring and system clipboard by using OSC 52.
|
||||
For example: send base64 encoded \\='foo\\=' to kill ring: echo -en \\='\\e]52;c;Zm9v\\a\\=',
|
||||
tmux can share its copy buffer to terminals by supporting osc52(like iterm2
|
||||
xterm) you can enable this feature for tmux by :
|
||||
set -g set-clipboard on #osc 52 copy paste share with iterm
|
||||
set -ga terminal-overrides ',xterm*:XT:Ms=\E]52;%p1%s;%p2%s\007'
|
||||
set -ga terminal-overrides ',screen*:XT:Ms=\E]52;%p1%s;%p2%s\007'
|
||||
set -ga terminal-overrides \\=',xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007\\='
|
||||
set -ga terminal-overrides \\=',screen*:XT:Ms=\\E]52;%p1%s;%p2%s\\007\\='
|
||||
|
||||
The clipboard querying/clearing functionality offered by OSC 52 is not
|
||||
implemented here,And for security reason, this feature is disabled
|
||||
@@ -372,7 +374,7 @@ This means that vterm will render bold with the default face weight."
|
||||
:group 'vterm)
|
||||
|
||||
(defcustom vterm-ignore-blink-cursor t
|
||||
"When t,vterm will ignore request from application to turn on/off cursor blink.
|
||||
"When t, vterm will ignore request from application to turn on/off cursor blink.
|
||||
|
||||
If nil, cursor in any window may begin to blink or not blink because
|
||||
`blink-cursor-mode`is a global minor mode in Emacs,
|
||||
@@ -521,16 +523,19 @@ of data. If nil, never delay. The units are seconds.")
|
||||
"Define a command that sends KEY with modifiers C and M to vterm."
|
||||
(declare (indent defun)
|
||||
(doc-string 3))
|
||||
`(defun ,(intern (format "vterm-send-%s" key))()
|
||||
,(format "Sends %s to the libvterm." key)
|
||||
(interactive)
|
||||
(vterm-send-key ,(char-to-string (get-byte (1- (length key)) key))
|
||||
,(let ((case-fold-search nil))
|
||||
(or (string-match-p "[A-Z]$" key)
|
||||
(string-match-p "S-" key)))
|
||||
,(string-match-p "M-" key)
|
||||
,(string-match-p "C-" key))))
|
||||
|
||||
`(progn (defun ,(intern (format "vterm-send-%s" key))()
|
||||
,(format "Sends %s to the libvterm." key)
|
||||
(interactive)
|
||||
(vterm-send-key ,(char-to-string (get-byte (1- (length key)) key))
|
||||
,(let ((case-fold-search nil))
|
||||
(or (string-match-p "[A-Z]$" key)
|
||||
(string-match-p "S-" key)))
|
||||
,(string-match-p "M-" key)
|
||||
,(string-match-p "C-" key)))
|
||||
(make-obsolete ',(intern (format "vterm-send-%s" key))
|
||||
"use `vterm--self-insert' or `vterm-send' or `vterm-send-key'."
|
||||
"v0.1")))
|
||||
(make-obsolete 'vterm-define-key "" "v0.1")
|
||||
(mapc (lambda (key)
|
||||
(eval `(vterm-define-key ,key)))
|
||||
(cl-loop for prefix in '("M-")
|
||||
@@ -558,29 +563,20 @@ Exceptions are defined by `vterm-keymap-exceptions'."
|
||||
for key = (format "<f%i>" number)
|
||||
unless (member key exceptions)
|
||||
collect key))
|
||||
(mapc (lambda (key)
|
||||
(define-key map (kbd key)
|
||||
(intern (format "vterm-send-%s" key))))
|
||||
(cl-loop for prefix in '("M-")
|
||||
append (cl-loop for char from ?A to ?Z
|
||||
for key = (format "%s%c" prefix char)
|
||||
unless (member key exceptions)
|
||||
collect key)))
|
||||
(mapc (lambda (key)
|
||||
(define-key map (kbd key)
|
||||
(intern (format "vterm-send-%s" key))))
|
||||
(cl-loop for prefix in '("C-" "M-" "C-S-" )
|
||||
append (cl-loop for char from ?a to ?z
|
||||
for key = (format "%s%c" prefix char)
|
||||
unless (member key exceptions)
|
||||
collect key)))
|
||||
(mapc (lambda (key)
|
||||
(define-key map (kbd key) 'ignore))
|
||||
(cl-loop for prefix in '("C-M-" "C-M-S-")
|
||||
append (cl-loop for char from ?a to ?z
|
||||
for key = (format "%s%c" prefix char)
|
||||
unless (member key exceptions)
|
||||
collect key))))
|
||||
(let ((esc-map (lookup-key map "\e"))
|
||||
(i 0)
|
||||
key)
|
||||
(unless esc-map (setq esc-map (make-keymap)))
|
||||
(while (< i 128)
|
||||
(setq key (make-string 1 i))
|
||||
(unless (member (key-description key) exceptions)
|
||||
(define-key map key 'vterm--self-insert))
|
||||
;; Avoid O and [. They are used in escape sequences for various keys.
|
||||
(unless (or (eq i ?O) (eq i 91))
|
||||
(unless (member (key-description key "\e") exceptions)
|
||||
(define-key esc-map key 'vterm--self-insert-meta)))
|
||||
(setq i (1+ i)))
|
||||
(define-key map "\e" esc-map)))
|
||||
|
||||
(defun vterm-xterm-paste (event)
|
||||
"Handle xterm paste EVENT in vterm."
|
||||
@@ -607,19 +603,21 @@ Exceptions are defined by `vterm-keymap-exceptions'."
|
||||
(define-key map [C-backspace] #'vterm-send-meta-backspace)
|
||||
(define-key map [return] #'vterm-send-return)
|
||||
(define-key map (kbd "RET") #'vterm-send-return)
|
||||
(define-key map [C-left] #'vterm-send-M-b)
|
||||
(define-key map [M-left] #'vterm-send-M-b)
|
||||
(define-key map [C-right] #'vterm-send-M-f)
|
||||
(define-key map [M-right] #'vterm-send-M-f)
|
||||
(define-key map [C-up] #'vterm-send-up)
|
||||
(define-key map [C-down] #'vterm-send-down)
|
||||
(define-key map [left] #'vterm-send-left)
|
||||
(define-key map [right] #'vterm-send-right)
|
||||
(define-key map [up] #'vterm-send-up)
|
||||
(define-key map [down] #'vterm-send-down)
|
||||
(define-key map [prior] #'vterm-send-prior)
|
||||
(define-key map [C-left] #'vterm--self-insert)
|
||||
(define-key map [M-left] #'vterm--self-insert)
|
||||
(define-key map [C-right] #'vterm--self-insert)
|
||||
(define-key map [M-right] #'vterm--self-insert)
|
||||
(define-key map [C-up] #'vterm--self-insert)
|
||||
(define-key map [C-down] #'vterm--self-insert)
|
||||
(define-key map [M-up] #'vterm--self-insert)
|
||||
(define-key map [M-down] #'vterm--self-insert)
|
||||
(define-key map [left] #'vterm--self-insert)
|
||||
(define-key map [right] #'vterm--self-insert)
|
||||
(define-key map [up] #'vterm--self-insert)
|
||||
(define-key map [down] #'vterm--self-insert)
|
||||
(define-key map [prior] #'vterm--self-insert)
|
||||
(define-key map [S-prior] #'scroll-down-command)
|
||||
(define-key map [next] #'vterm-send-next)
|
||||
(define-key map [next] #'vterm--self-insert)
|
||||
(define-key map [S-next] #'scroll-up-command)
|
||||
(define-key map [home] #'vterm--self-insert)
|
||||
(define-key map [end] #'vterm--self-insert)
|
||||
@@ -633,16 +631,16 @@ Exceptions are defined by `vterm-keymap-exceptions'."
|
||||
(define-key map (kbd "C-SPC") #'vterm--self-insert)
|
||||
(define-key map (kbd "S-SPC") #'vterm-send-space)
|
||||
(define-key map (kbd "C-_") #'vterm--self-insert)
|
||||
(define-key map (kbd "C-/") #'vterm-undo)
|
||||
(define-key map (kbd "M-.") #'vterm-send-meta-dot)
|
||||
(define-key map (kbd "M-,") #'vterm-send-meta-comma)
|
||||
(define-key map [remap undo] #'vterm-undo)
|
||||
(define-key map (kbd "M-.") #'vterm--self-insert)
|
||||
(define-key map (kbd "M-,") #'vterm--self-insert)
|
||||
(define-key map (kbd "C-c C-y") #'vterm--self-insert)
|
||||
(define-key map (kbd "C-c C-c") #'vterm-send-C-c)
|
||||
(define-key map (kbd "C-c C-c") #'vterm--self-insert)
|
||||
(define-key map (kbd "C-c C-l") #'vterm-clear-scrollback)
|
||||
(define-key map (kbd "C-l") #'vterm-clear)
|
||||
(define-key map (kbd "C-\\") #'vterm-send-ctrl-slash)
|
||||
(define-key map (kbd "C-c C-g") #'vterm-send-C-g)
|
||||
(define-key map (kbd "C-c C-u") #'vterm-send-C-u)
|
||||
(define-key map (kbd "C-\\") #'vterm--self-insert)
|
||||
(define-key map (kbd "C-c C-g") #'vterm--self-insert)
|
||||
(define-key map (kbd "C-c C-u") #'vterm--self-insert)
|
||||
(define-key map [remap self-insert-command] #'vterm--self-insert)
|
||||
(define-key map (kbd "C-c C-r") #'vterm-reset-cursor-point)
|
||||
(define-key map (kbd "C-c C-n") #'vterm-next-prompt)
|
||||
@@ -879,25 +877,20 @@ will invert `vterm-copy-exclude-prompt' for that call."
|
||||
|
||||
;;; Commands
|
||||
|
||||
(defun vterm--self-insert-meta ()
|
||||
(interactive)
|
||||
(when vterm--term
|
||||
(dolist (key (vterm--translate-event-to-args
|
||||
last-command-event :meta))
|
||||
(apply #'vterm-send-key key))))
|
||||
|
||||
(defun vterm--self-insert ()
|
||||
"Send invoking key to libvterm."
|
||||
(interactive)
|
||||
(when vterm--term
|
||||
(let* ((modifiers (event-modifiers last-command-event))
|
||||
(shift (memq 'shift modifiers))
|
||||
(meta (memq 'meta modifiers))
|
||||
(ctrl (memq 'control modifiers))
|
||||
(raw-key (event-basic-type last-command-event))
|
||||
(ev-keys))
|
||||
(if input-method-function
|
||||
(let ((inhibit-read-only t))
|
||||
(setq ev-keys (funcall input-method-function raw-key))
|
||||
(when (listp ev-keys)
|
||||
(dolist (k ev-keys)
|
||||
(when-let ((key (key-description (vector k))))
|
||||
(vterm-send-key key shift meta ctrl)))))
|
||||
(when-let ((key (key-description (vector raw-key))))
|
||||
(vterm-send-key key shift meta ctrl))))))
|
||||
(dolist (key (vterm--translate-event-to-args
|
||||
last-command-event))
|
||||
(apply #'vterm-send-key key))))
|
||||
|
||||
(defun vterm-send-key (key &optional shift meta ctrl accept-proc-output)
|
||||
"Send KEY to libvterm with optional modifiers SHIFT, META and CTRL."
|
||||
@@ -905,8 +898,6 @@ will invert `vterm-copy-exclude-prompt' for that call."
|
||||
(when vterm--term
|
||||
(let ((inhibit-redisplay t)
|
||||
(inhibit-read-only t))
|
||||
(when (and (not (symbolp last-command-event)) shift (not meta) (not ctrl))
|
||||
(setq key (upcase key)))
|
||||
(vterm--update vterm--term key shift meta ctrl)
|
||||
(setq vterm--redraw-immididately t)
|
||||
(when accept-proc-output
|
||||
@@ -914,13 +905,19 @@ will invert `vterm-copy-exclude-prompt' for that call."
|
||||
|
||||
(defun vterm-send (key)
|
||||
"Send KEY to libvterm. KEY can be anything `kbd' understands."
|
||||
(let* ((event (listify-key-sequence (kbd key)))
|
||||
(modifiers (event-modifiers event))
|
||||
(base (event-basic-type event)))
|
||||
(vterm-send-key (char-to-string base)
|
||||
(memq 'shift modifiers)
|
||||
(memq 'meta modifiers)
|
||||
(memq 'control modifiers))))
|
||||
(dolist (key (vterm--translate-event-to-args
|
||||
(listify-key-sequence (kbd key))))
|
||||
(apply #'vterm-send-key key)))
|
||||
|
||||
(defun vterm-send-next-key ()
|
||||
"Read next input event and send it to the libvterm.
|
||||
|
||||
With this you can directly send modified keys to applications
|
||||
running in the terminal (like Emacs or Nano)."
|
||||
(interactive)
|
||||
(dolist (key (vterm--translate-event-to-args
|
||||
(read-event)))
|
||||
(apply #'vterm-send-key key)))
|
||||
|
||||
(defun vterm-send-start ()
|
||||
"Output from the system is started when the system receives START."
|
||||
@@ -970,46 +967,55 @@ will invert `vterm-copy-exclude-prompt' for that call."
|
||||
"Send `<up>' to the libvterm."
|
||||
(interactive)
|
||||
(vterm-send-key "<up>"))
|
||||
(make-obsolete 'vterm-send-up 'vterm--self-insert "v0.1")
|
||||
|
||||
(defun vterm-send-down ()
|
||||
"Send `<down>' to the libvterm."
|
||||
(interactive)
|
||||
(vterm-send-key "<down>"))
|
||||
(make-obsolete 'vterm-send-down 'vterm--self-insert "v0.1")
|
||||
|
||||
(defun vterm-send-left ()
|
||||
"Send `<left>' to the libvterm."
|
||||
(interactive)
|
||||
(vterm-send-key "<left>"))
|
||||
(make-obsolete 'vterm-send-left 'vterm--self-insert "v0.1")
|
||||
|
||||
(defun vterm-send-right ()
|
||||
"Send `<right>' to the libvterm."
|
||||
(interactive)
|
||||
(vterm-send-key "<right>"))
|
||||
(make-obsolete 'vterm-send-right 'vterm--self-insert "v0.1")
|
||||
|
||||
(defun vterm-send-prior ()
|
||||
"Send `<prior>' to the libvterm."
|
||||
(interactive)
|
||||
(vterm-send-key "<prior>"))
|
||||
(make-obsolete 'vterm-send-prior 'vterm--self-insert "v0.1")
|
||||
|
||||
(defun vterm-send-next ()
|
||||
"Send `<next>' to the libvterm."
|
||||
(interactive)
|
||||
(vterm-send-key "<next>"))
|
||||
(make-obsolete 'vterm-send-next 'vterm--self-insert "v0.1")
|
||||
|
||||
(defun vterm-send-meta-dot ()
|
||||
"Send `M-.' to the libvterm."
|
||||
(interactive)
|
||||
(vterm-send-key "." nil t))
|
||||
(make-obsolete 'vterm-send-meta-dot 'vterm--self-insert "v0.1")
|
||||
|
||||
(defun vterm-send-meta-comma ()
|
||||
"Send `M-,' to the libvterm."
|
||||
(interactive)
|
||||
(vterm-send-key "," nil t))
|
||||
(make-obsolete 'vterm-send-meta-comma 'vterm--self-insert "v0.1")
|
||||
|
||||
(defun vterm-send-ctrl-slash ()
|
||||
"Send `C-\' to the libvterm."
|
||||
(interactive)
|
||||
(vterm-send-key "\\" nil nil t))
|
||||
(make-obsolete 'vterm-send-ctrl-slash 'vterm--self-insert "v0.1")
|
||||
|
||||
(defun vterm-send-escape ()
|
||||
"Send `<escape>' to the libvterm."
|
||||
@@ -1034,7 +1040,7 @@ prefix argument ARG or with \\[universal-argument]."
|
||||
(and vterm-clear-scrollback-when-clearing (not arg))
|
||||
(and arg (not vterm-clear-scrollback-when-clearing)))
|
||||
(vterm-clear-scrollback))
|
||||
(vterm-send-C-l))
|
||||
(vterm-send-key "l" nil nil :ctrl))
|
||||
|
||||
(defun vterm-undo ()
|
||||
"Send `C-_' to the libvterm."
|
||||
@@ -1103,44 +1109,86 @@ Provide similar behavior as `insert' for vterm."
|
||||
(defun vterm-delete-region (start end)
|
||||
"Delete the text between START and END for vterm. "
|
||||
(when vterm--term
|
||||
(if (vterm-goto-char start)
|
||||
(cl-loop repeat (- end start) do
|
||||
(vterm-send-key "<delete>" nil nil nil t))
|
||||
(let ((inhibit-read-only nil))
|
||||
(vterm--delete-region start end)))))
|
||||
(save-excursion
|
||||
(when (get-text-property start 'vterm-line-wrap)
|
||||
;; skip over the fake newline when start there.
|
||||
(setq start (1+ start))))
|
||||
;; count of chars after fake newline removed
|
||||
(let ((count (length (filter-buffer-substring start end))))
|
||||
(if (vterm-goto-char start)
|
||||
(cl-loop repeat count do
|
||||
(vterm-send-key "<delete>" nil nil nil t))
|
||||
(let ((inhibit-read-only nil))
|
||||
(vterm--delete-region start end))))))
|
||||
|
||||
(defun vterm-goto-char (pos)
|
||||
"Set point to POSITION for vterm.
|
||||
|
||||
The return value is `t' when point moved successfully.
|
||||
It will reset to original position if it can't move there."
|
||||
The return value is `t' when point moved successfully."
|
||||
(when (and vterm--term
|
||||
(vterm-cursor-in-command-buffer-p)
|
||||
(vterm-cursor-in-command-buffer-p pos))
|
||||
(let ((moved t)
|
||||
(origin-point (point))
|
||||
pt cursor-pos succ)
|
||||
(vterm-reset-cursor-point)
|
||||
(setq cursor-pos (point))
|
||||
(setq pt cursor-pos)
|
||||
(while (and (> pos pt) moved)
|
||||
(vterm-send-key "<right>" nil nil nil t)
|
||||
(setq moved (not (= pt (point))))
|
||||
(setq pt (point)))
|
||||
(setq pt (point))
|
||||
(setq moved t)
|
||||
(while (and (< pos pt) moved)
|
||||
(vterm-send-key "<left>" nil nil nil t)
|
||||
(setq moved (not (= pt (point))))
|
||||
(setq pt (point)))
|
||||
(setq succ (= pos (point)))
|
||||
(unless succ
|
||||
(vterm-goto-char cursor-pos)
|
||||
(goto-char origin-point))
|
||||
succ)))
|
||||
(vterm-reset-cursor-point)
|
||||
(let ((diff (- pos (point))))
|
||||
(cond
|
||||
((zerop diff) t) ;do not need move
|
||||
((< diff 0) ;backward
|
||||
(while (and
|
||||
(vterm--backward-char)
|
||||
(> (point) pos)))
|
||||
(<= (point) pos))
|
||||
(t
|
||||
(while (and (vterm--forward-char)
|
||||
(< (point) pos)))
|
||||
(>= (point) pos))))))
|
||||
|
||||
;;; Internal
|
||||
|
||||
(defun vterm--forward-char ()
|
||||
"Move point 1 character forward ().
|
||||
|
||||
the return value is `t' when cursor moved."
|
||||
(vterm-reset-cursor-point)
|
||||
(let ((pt (point)))
|
||||
(vterm-send-key "<right>" nil nil nil t)
|
||||
(cond
|
||||
((= (point) (1+ pt)) t)
|
||||
((and (> (point) pt)
|
||||
;; move over the fake newline
|
||||
(get-text-property (1- (point)) 'vterm-line-wrap))
|
||||
t)
|
||||
((and (= (point) (+ 4 pt))
|
||||
(looking-back (regexp-quote "^[[C") nil)) ;escape code for <right>
|
||||
(dotimes (_ 3) (vterm-send-key "<backspace>" nil nil nil t)) ;;delete "^[[C"
|
||||
nil)
|
||||
((> (point) (1+ pt)) ;auto suggest
|
||||
(vterm-send-key "_" nil nil t t) ;undo C-_
|
||||
nil)
|
||||
(t nil))))
|
||||
|
||||
|
||||
|
||||
(defun vterm--backward-char ()
|
||||
"Move point N characters backward.
|
||||
|
||||
Return count of moved characeters."
|
||||
(vterm-reset-cursor-point)
|
||||
(let ((pt (point)))
|
||||
(vterm-send-key "<left>" nil nil nil t)
|
||||
(cond
|
||||
((= (point) (1- pt)) t)
|
||||
((and (= (point) (- pt 2))
|
||||
;; backward cross fake newline
|
||||
(string-equal (buffer-substring-no-properties
|
||||
(1+ (point)) (+ 2 (point)))
|
||||
"\n"))
|
||||
t)
|
||||
((and (= (point) (+ 4 pt))
|
||||
(looking-back (regexp-quote "^[[D") nil)) ;escape code for <left>
|
||||
(dotimes (_ 3) (vterm-send-key "<backspace>" nil nil nil t)) ;;delete "^[[D"
|
||||
nil)
|
||||
(t nil))))
|
||||
|
||||
(defun vterm--delete-region(start end)
|
||||
"A wrapper for `delete-region'."
|
||||
(funcall vterm--delete-region-function start end))
|
||||
@@ -1153,6 +1201,33 @@ It will reset to original position if it can't move there."
|
||||
"A wrapper for `delete-char'."
|
||||
(funcall vterm--delete-char-function n killflag))
|
||||
|
||||
(defun vterm--translate-event-to-args (event &optional meta)
|
||||
"Translate EVENT as list of args for `vterm-send-key'.
|
||||
|
||||
When some input method is enabled, one key may generate
|
||||
several characters, so the result of this function is a list,
|
||||
looks like: ((\"m\" :shift ))"
|
||||
(let* ((modifiers (event-modifiers event))
|
||||
(shift (memq 'shift modifiers))
|
||||
(meta (or meta (memq 'meta modifiers)))
|
||||
(ctrl (memq 'control modifiers))
|
||||
(raw-key (event-basic-type event))
|
||||
(ev-keys) keys)
|
||||
(if input-method-function
|
||||
(let ((inhibit-read-only t))
|
||||
(setq ev-keys (funcall input-method-function raw-key))
|
||||
(when (listp ev-keys)
|
||||
(dolist (k ev-keys)
|
||||
(when-let ((key (key-description (vector k))))
|
||||
(when (and (not (symbolp event)) shift (not meta) (not ctrl))
|
||||
(setq key (upcase key)))
|
||||
(setq keys (append keys (list (list key shift meta ctrl))))))))
|
||||
(when-let ((key (key-description (vector raw-key))))
|
||||
(when (and (not (symbolp event)) shift (not meta) (not ctrl))
|
||||
(setq key (upcase key)))
|
||||
(setq keys (list (list key shift meta ctrl)))))
|
||||
keys))
|
||||
|
||||
(defun vterm--invalidate ()
|
||||
"The terminal buffer is invalidated, the buffer needs redrawing."
|
||||
(if (and (not vterm--redraw-immididately)
|
||||
@@ -1189,31 +1264,25 @@ Argument BUFFER the terminal buffer."
|
||||
(when (cl-member (selected-window) windows :test #'eq)
|
||||
(set-window-hscroll (selected-window) 0))))))))
|
||||
|
||||
(defun vterm--selection (targets data)
|
||||
;; see VTermSelectionMask in vterm.el
|
||||
;; VTERM_SELECTION_CLIPBOARD = (1<<0),
|
||||
;; VTERM_SELECTION_PRIMARY = (1<<1),
|
||||
(defconst vterm--selection-clipboard 1) ;(1<<0)
|
||||
(defconst vterm--selection-primary 2) ;(1<<1)
|
||||
(defun vterm--set-selection (mask data)
|
||||
"OSC 52 Manipulate Selection Data.
|
||||
Search Manipulate Selection Data in
|
||||
https://invisible-island.net/xterm/ctlseqs/ctlseqs.html ."
|
||||
(when vterm-enable-manipulate-selection-data-by-osc52
|
||||
(unless (or (string-equal data "?")
|
||||
(string-empty-p data))
|
||||
(let* ((inhibit-eol-conversion t)
|
||||
(decoded-data (decode-coding-string
|
||||
(base64-decode-string data) locale-coding-system))
|
||||
(select-enable-clipboard select-enable-clipboard)
|
||||
(select-enable-primary select-enable-primary))
|
||||
;; https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
;; c , p , q , s , 0 , 1 , 2 , 3 , 4 , 5 , 6 , and 7
|
||||
;; clipboard, primary, secondary, select, or cut buffers 0 through 7
|
||||
(unless (string-empty-p targets)
|
||||
(setq select-enable-clipboard nil)
|
||||
(setq select-enable-primary nil))
|
||||
(when (cl-find ?c targets)
|
||||
(setq select-enable-clipboard t))
|
||||
(when (cl-find ?p targets)
|
||||
(setq select-enable-primary t))
|
||||
|
||||
(kill-new decoded-data)
|
||||
(message "kill-ring is updated by vterm OSC 52(Manipulate Selection Data)")))))
|
||||
(let ((select-enable-clipboard select-enable-clipboard)
|
||||
(select-enable-primary select-enable-primary))
|
||||
(setq select-enable-clipboard
|
||||
(logand mask vterm--selection-clipboard))
|
||||
(setq select-enable-primary
|
||||
(logand mask vterm--selection-primary))
|
||||
(kill-new data)
|
||||
(message "kill-ring is updated by vterm OSC 52(Manipulate Selection Data)"))
|
||||
))
|
||||
|
||||
;;; Entry Points
|
||||
|
||||
@@ -1292,7 +1361,7 @@ value of `vterm-buffer-name'."
|
||||
"\\(?:[\r\n\000\007\t\b\016\017]\\|"
|
||||
;; a C1 escape coded character (see [ECMA-48] section 5.3 "Elements
|
||||
;; of the C1 set"),
|
||||
"\e\\(?:[DM78c]\\|"
|
||||
"\e\\(?:[DM78c=]\\|"
|
||||
;; another Emacs specific control sequence for term.el,
|
||||
"AnSiT[^\n]+\n\\|"
|
||||
;; another Emacs specific control sequence for vterm.el
|
||||
@@ -1436,7 +1505,7 @@ If option DELETE-WHOLE-LINE is non-nil, then this command kills
|
||||
the whole line including its terminating newline"
|
||||
(save-excursion
|
||||
(when (vterm--goto-line line-num)
|
||||
(vterm--delete-region (point) (point-at-eol count))
|
||||
(vterm--delete-region (point) (line-end-position count))
|
||||
(when (and delete-whole-line
|
||||
(looking-at "\n"))
|
||||
(vterm--delete-char 1)))))
|
||||
@@ -1525,7 +1594,8 @@ the called functions."
|
||||
(f (assoc command vterm-eval-cmds)))
|
||||
(if f
|
||||
(apply (cadr f) args)
|
||||
(message "Failed to find command: %s" command))))
|
||||
(message "Failed to find command: %s. To execute a command,
|
||||
add it to the `vterm-eval-cmd' list" command))))
|
||||
|
||||
;; TODO: Improve doc string, it should not point to the readme but it should
|
||||
;; be self-contained.
|
||||
@@ -1555,7 +1625,7 @@ in README."
|
||||
(promp-pt (vterm--get-prompt-point)))
|
||||
(when promp-pt (goto-char promp-pt))
|
||||
(cl-loop repeat (or n 1) do
|
||||
(setq pt (next-single-property-change (point-at-bol 2) 'vterm-prompt))
|
||||
(setq pt (next-single-property-change (line-beginning-position 2) 'vterm-prompt))
|
||||
(when pt (goto-char pt))))
|
||||
(term-next-prompt n)))
|
||||
|
||||
@@ -1622,12 +1692,9 @@ More information see `vterm--prompt-tracking-enabled-p' and
|
||||
"Check whether cursor in command buffer area."
|
||||
(save-excursion
|
||||
(vterm-reset-cursor-point)
|
||||
(let ((promp-pt (vterm--get-prompt-point))
|
||||
eol)
|
||||
(let ((promp-pt (vterm--get-prompt-point)))
|
||||
(when promp-pt
|
||||
(goto-char promp-pt)
|
||||
(setq eol (vterm--get-end-of-line))
|
||||
(<= promp-pt (or pt (vterm--get-cursor-point)) eol)))))
|
||||
(<= promp-pt (or pt (vterm--get-cursor-point)))))))
|
||||
|
||||
(defun vterm-beginning-of-line ()
|
||||
"Move point to the beginning of the line.
|
||||
@@ -1662,7 +1729,7 @@ Effectively toggle between the two positions."
|
||||
(defun vterm--remove-fake-newlines ()
|
||||
"Filter out injected newlines were injected when rendering the terminal.
|
||||
|
||||
These newlines were tagged with 'vterm-line-wrap property so we
|
||||
These newlines were tagged with \\='vterm-line-wrap property so we
|
||||
can find them and remove them."
|
||||
(goto-char (point-min))
|
||||
(let (fake-newline)
|
||||
|
||||
Reference in New Issue
Block a user