2022-11-24 19:07:08 +06:00
|
|
|
|
;;; eat.el --- Emulate A Terminal, in a region, in a buffer and in Eshell -*- lexical-binding: t; -*-
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
2023-01-22 22:40:27 +06:00
|
|
|
|
;; Copyright (C) 2022, 2023 Akib Azmain Turja.
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
;; Author: Akib Azmain Turja <akib@disroot.org>
|
|
|
|
|
;; Created: 2022-08-15
|
2023-03-28 14:08:07 +06:00
|
|
|
|
;; Version: 0.6.1
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Package-Requires: ((emacs "28.1"))
|
|
|
|
|
;; Keywords: terminals processes
|
|
|
|
|
;; Homepage: https://codeberg.org/akib/emacs-eat
|
|
|
|
|
|
|
|
|
|
;; This file is not part of GNU Emacs.
|
|
|
|
|
|
|
|
|
|
;; This file is free software; you can redistribute it and/or modify
|
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
|
|
|
|
;; the Free Software Foundation; either version 3, or (at your option)
|
|
|
|
|
;; any later version.
|
|
|
|
|
|
|
|
|
|
;; This program is distributed in the hope that it will be useful,
|
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
;; For a full copy of the GNU General Public License
|
|
|
|
|
;; see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
|
|
;; Eat's name self-explainary, it stands for "Emulate A Terminal".
|
|
|
|
|
;; Eat is a terminal emulator. It can run most (if not all)
|
|
|
|
|
;; full-screen terminal programs, including Emacs.
|
|
|
|
|
|
|
|
|
|
;; It is pretty fast, more than three times faster than Term, despite
|
|
|
|
|
;; being implemented entirely in Emacs Lisp. So fast that you can
|
|
|
|
|
;; comfortably run Emacs inside Eat, or even use your Emacs as a
|
|
|
|
|
;; terminal multiplexer.
|
|
|
|
|
|
|
|
|
|
;; It has many feature that other Emacs terminal emulator still don't
|
|
|
|
|
;; have, for example complete mouse support.
|
|
|
|
|
|
|
|
|
|
;; It flickers less than other Emacs terminal emulator, so you get
|
|
|
|
|
;; more performance and a smooth experience.
|
|
|
|
|
|
|
|
|
|
;; To start Eat, run M-x eat. Eat has three keybinding modes:
|
|
|
|
|
|
|
|
|
|
;; * "emacs" mode: No special keybinding, except the following:
|
|
|
|
|
|
|
|
|
|
;; * `C-c' `C-s': Switch to semi-char mode.
|
|
|
|
|
;; * `C-c' `C-j': Switch to char mode.
|
|
|
|
|
;; * `C-c' `C-k': Kill process.
|
|
|
|
|
|
|
|
|
|
;; * "semi-char" mode: Most keys are bound to send the key to the
|
|
|
|
|
;; terminal, except the following keys: `C-\', `C-c', `C-x',
|
|
|
|
|
;; `C-g', `C-h', `C-M-c', `C-u', `M-x', `M-:', `M-!', `M-&'. The
|
|
|
|
|
;; following special keybinding are available:
|
|
|
|
|
|
|
|
|
|
;; * `C-q': Send next key to the terminal.
|
|
|
|
|
;; * `C-y': Like `yank', but send the text to the terminal.
|
|
|
|
|
;; * `M-y': Like `yank-pop', but send the text to the terminal.
|
|
|
|
|
;; * `C-c' `C-k': Kill process.
|
|
|
|
|
|
|
|
|
|
;; * "char" mode: All supported keys are bound to send the key to
|
|
|
|
|
;; the terminal, except `C-M-m' or `M-RET', which is bound to
|
|
|
|
|
;; switch to semi-char mode.
|
|
|
|
|
|
|
|
|
|
;; If you like Eshell, then there is a good news for you. Eat
|
|
|
|
|
;; integrates with Eshell. Eat has two global minor modes for Eshell:
|
|
|
|
|
|
|
|
|
|
;; * `eat-eshell-visual-command-mode': Run visual commands with Eat
|
|
|
|
|
;; instead of Term.
|
|
|
|
|
|
|
|
|
|
;; * `eat-eshell-mode': Run Eat inside Eshell. After enabling this,
|
|
|
|
|
;; you can run full-screen terminal programs directly in Eshell.
|
|
|
|
|
;; You have three keybinding modes here too, except that `C-c'
|
|
|
|
|
;; `C-k' is not special (i.e. not bound by Eat) in "emacs" mode
|
|
|
|
|
;; and "line" mode.
|
|
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
2022-11-30 12:29:05 +06:00
|
|
|
|
(require 'subr-x)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(require 'cl-lib)
|
|
|
|
|
(require 'ansi-color)
|
|
|
|
|
(require 'shell)
|
2022-12-01 01:40:17 +06:00
|
|
|
|
(require 'url)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
2023-01-19 15:45:44 +06:00
|
|
|
|
;; Needed by `eat-reload'.
|
|
|
|
|
(defvar eat--being-loaded nil
|
|
|
|
|
"Non-nil means Eat is being loaded.")
|
|
|
|
|
|
|
|
|
|
(setq eat--being-loaded t)
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
;;;; User Options.
|
|
|
|
|
|
|
|
|
|
(defgroup eat nil
|
|
|
|
|
"Emulate A Terminal."
|
|
|
|
|
:group 'processes
|
|
|
|
|
:group 'terminals
|
|
|
|
|
:link '(url-link "https://codeberg.org/akib/emacs-eat"))
|
|
|
|
|
|
|
|
|
|
(defgroup eat-term nil
|
|
|
|
|
"Eat terminal emulator."
|
|
|
|
|
:group 'eat)
|
|
|
|
|
|
|
|
|
|
(defgroup eat-ui nil
|
|
|
|
|
"Eat user interface."
|
|
|
|
|
:group 'eat)
|
|
|
|
|
|
|
|
|
|
(defgroup eat-eshell nil
|
|
|
|
|
"Eat Eshell integration."
|
|
|
|
|
:group 'eat)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-buffer-name "*eat*"
|
|
|
|
|
"The basename used for Eat buffers.
|
|
|
|
|
|
|
|
|
|
This is the default name used when running Eat."
|
|
|
|
|
:type 'string
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-kill-buffer-on-exit nil
|
|
|
|
|
"Non-nil means automatically kill Eat buffer when process exits."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-term-scrollback-size 131072 ; 128 K
|
|
|
|
|
"Size of scrollback area in characters. nil means unlimited."
|
|
|
|
|
:type '(choice integer (const nil))
|
|
|
|
|
:group 'eat-term
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-enable-kill-from-terminal t
|
|
|
|
|
"Non-nil means allow terminal program to add text to `kill-ring'.
|
|
|
|
|
|
|
|
|
|
When non-nil, terminal program can send special escape sequence to add
|
|
|
|
|
some text to `kill-ring'."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'eat-ui
|
|
|
|
|
:group 'eat-eshell)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-enable-yank-to-terminal nil
|
|
|
|
|
"Non-nil means allow terminal program to get text from `kill-ring'.
|
|
|
|
|
|
|
|
|
|
When non-nil, terminal program can get killed text from `kill-ring'.
|
|
|
|
|
This is left disabled for security reasons."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'eat-ui
|
|
|
|
|
:group 'eat-eshell)
|
|
|
|
|
|
2023-02-07 17:13:10 +06:00
|
|
|
|
(defcustom eat-query-before-killing-running-terminal 'auto
|
|
|
|
|
"Whether to query before killing running terminal.
|
|
|
|
|
|
|
|
|
|
If the value is t, always query. If the value is nil, never query.
|
|
|
|
|
If the value is `auto', query if a shell command is running (shell
|
|
|
|
|
integration needs to be enabled to use this properly)."
|
|
|
|
|
:type '(choice (const :tag "Yes" t)
|
|
|
|
|
(const :tag "No" nil)
|
|
|
|
|
(const :tag "If a shell command is running" auto))
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
2022-12-14 14:12:34 +06:00
|
|
|
|
(defcustom eat-eshell-fallback-if-stty-not-available 'ask
|
|
|
|
|
"What to do if `stty' is unavailable.
|
|
|
|
|
|
|
|
|
|
`stty' is a dependency to setup terminal. If `stty' is unavailable,
|
|
|
|
|
Eat won't be able to setup terminal, so any input won't be visible.
|
|
|
|
|
|
|
|
|
|
The value should be any of the following:
|
|
|
|
|
|
|
|
|
|
nil Do nothing.
|
|
|
|
|
t Fallback to plain Eshell if `stty' is not available.
|
|
|
|
|
`ask' Ask what to do.
|
|
|
|
|
FUNCTION Call FUNCTION with the command and arguments (using
|
|
|
|
|
`apply') and fallback to plain Eshell if it returns
|
|
|
|
|
nil."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'eat-eshell)
|
|
|
|
|
|
2023-01-16 12:11:25 +06:00
|
|
|
|
(defcustom eat-semi-char-non-bound-keys
|
|
|
|
|
'([?\C-x] [?\C-\\] [?\C-q] [?\C-g] [?\C-h] [?\e ?\C-c] [?\C-u]
|
2023-01-22 22:34:08 +06:00
|
|
|
|
[?\e ?x] [?\e ?:] [?\e ?!] [?\e ?&]
|
|
|
|
|
[C-insert] [M-insert] [S-insert] [C-M-insert]
|
|
|
|
|
[C-S-insert] [M-S-insert] [C-M-S-insert]
|
|
|
|
|
[C-delete] [M-delete] [S-delete] [C-M-delete]
|
|
|
|
|
[C-S-delete] [M-S-delete] [C-M-S-delete]
|
|
|
|
|
[C-deletechar] [M-deletechar]
|
|
|
|
|
[S-deletechar] [C-M-deletechar] [C-S-deletechar]
|
|
|
|
|
[M-S-deletechar] [C-M-S-deletechar]
|
|
|
|
|
[C-up] [C-down] [C-right] [C-left]
|
|
|
|
|
[M-up] [M-down] [M-right] [M-left]
|
|
|
|
|
[S-up] [S-down] [S-right] [S-left]
|
|
|
|
|
[C-M-up] [C-M-down] [C-M-right] [C-M-left]
|
|
|
|
|
[C-S-up] [C-S-down] [C-S-right] [C-S-left]
|
|
|
|
|
[M-S-up] [M-S-down] [M-S-right] [M-S-left]
|
|
|
|
|
[C-M-S-up] [C-M-S-down] [C-M-S-right] [C-M-S-left]
|
|
|
|
|
[C-home] [M-home] [S-home] [C-M-home] [C-S-home]
|
|
|
|
|
[M-S-home] [C-M-S-home]
|
|
|
|
|
[C-end] [M-end] [S-end] [C-M-end] [C-S-end]
|
|
|
|
|
[M-S-end] [C-M-S-end]
|
|
|
|
|
[C-prior] [M-prior] [S-prior] [C-M-prior]
|
|
|
|
|
[C-S-prior] [M-S-prior] [C-M-S-prior]
|
|
|
|
|
[C-next] [M-next] [S-next] [C-M-next] [C-S-next]
|
|
|
|
|
[M-S-next] [C-M-S-next])
|
2023-01-16 12:11:25 +06:00
|
|
|
|
"List of keys not bound in Eat \"semi-char\" mode.
|
|
|
|
|
|
|
|
|
|
Keys appearing in this list are not bound to send the key to terminal.
|
|
|
|
|
Eat might still bound them to do something else (for example, changing
|
|
|
|
|
keybinding mode).
|
|
|
|
|
|
2023-01-18 17:22:13 +06:00
|
|
|
|
Each element is a vector of form [KEY] or [?\\e KEY], meaning KEY or
|
2023-01-19 15:45:44 +06:00
|
|
|
|
M-KEY shouldn't be bound. KEY shouldn't contain meta (Alt) modifier.
|
|
|
|
|
|
|
|
|
|
When changing this from Lisp, make sure to call
|
|
|
|
|
`eat-update-semi-char-mode-map' to update the keymap and reload Eat to
|
|
|
|
|
make the changes effective."
|
2023-01-16 12:11:25 +06:00
|
|
|
|
:type '(repeat sexp)
|
|
|
|
|
:set (lambda (sym val)
|
|
|
|
|
(set-default-toplevel-value sym val)
|
2023-01-19 15:45:44 +06:00
|
|
|
|
(when (and (not eat--being-loaded)
|
|
|
|
|
(boundp 'eat-semi-char-mode-map))
|
|
|
|
|
(eat-update-semi-char-mode-map)
|
|
|
|
|
(eat-reload)))
|
2023-01-16 12:11:25 +06:00
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-eshell-semi-char-non-bound-keys
|
|
|
|
|
'([?\C-\\] [?\C-x] [?\C-g] [?\C-h] [?\e ?\C-c] [?\C-u] [?\C-q]
|
2023-01-22 22:34:08 +06:00
|
|
|
|
[?\e ?x] [?\e ?:] [?\e ?!] [?\e ?&]
|
|
|
|
|
[C-insert] [M-insert] [S-insert] [C-M-insert]
|
|
|
|
|
[C-S-insert] [M-S-insert] [C-M-S-insert]
|
|
|
|
|
[C-delete] [M-delete] [S-delete] [C-M-delete]
|
|
|
|
|
[C-S-delete] [M-S-delete] [C-M-S-delete]
|
|
|
|
|
[C-deletechar] [M-deletechar]
|
|
|
|
|
[S-deletechar] [C-M-deletechar] [C-S-deletechar]
|
|
|
|
|
[M-S-deletechar] [C-M-S-deletechar]
|
|
|
|
|
[C-up] [C-down] [C-right] [C-left]
|
|
|
|
|
[M-up] [M-down] [M-right] [M-left]
|
|
|
|
|
[S-up] [S-down] [S-right] [S-left]
|
|
|
|
|
[C-M-up] [C-M-down] [C-M-right] [C-M-left]
|
|
|
|
|
[C-S-up] [C-S-down] [C-S-right] [C-S-left]
|
|
|
|
|
[M-S-up] [M-S-down] [M-S-right] [M-S-left]
|
|
|
|
|
[C-M-S-up] [C-M-S-down] [C-M-S-right] [C-M-S-left]
|
|
|
|
|
[C-home] [M-home] [S-home] [C-M-home] [C-S-home]
|
|
|
|
|
[M-S-home] [C-M-S-home]
|
|
|
|
|
[C-end] [M-end] [S-end] [C-M-end] [C-S-end]
|
|
|
|
|
[M-S-end] [C-M-S-end]
|
|
|
|
|
[C-prior] [M-prior] [S-prior] [C-M-prior]
|
|
|
|
|
[C-S-prior] [M-S-prior] [C-M-S-prior]
|
|
|
|
|
[C-next] [M-next] [S-next] [C-M-next] [C-S-next]
|
|
|
|
|
[M-S-next] [C-M-S-next])
|
2023-01-16 12:11:25 +06:00
|
|
|
|
"List of keys not bound in Eat-Eshell \"semi-char\" mode.
|
|
|
|
|
|
|
|
|
|
Keys appearing in this list are not bound to send the key to terminal.
|
|
|
|
|
Eat might still bound them to do something else (for example, changing
|
|
|
|
|
keybinding mode).
|
|
|
|
|
|
2023-01-18 17:22:13 +06:00
|
|
|
|
Each element is a vector of form [KEY] or [?\\e KEY], meaning KEY or
|
2023-01-19 15:45:44 +06:00
|
|
|
|
M-KEY shouldn't be bound. KEY shouldn't contain meta (Alt) modifier.
|
|
|
|
|
|
|
|
|
|
When changing this from Lisp, make sure to call
|
|
|
|
|
`eat-eshell-update-semi-char-mode-map' to update the keymap and reload
|
|
|
|
|
Eat to make the changes effective."
|
2023-01-16 12:11:25 +06:00
|
|
|
|
:type '(repeat sexp)
|
|
|
|
|
:set (lambda (sym val)
|
|
|
|
|
(set-default-toplevel-value sym val)
|
2023-01-19 15:45:44 +06:00
|
|
|
|
(when (and (not eat--being-loaded)
|
|
|
|
|
(boundp 'eat-eshell-semi-char-mode-map))
|
|
|
|
|
(eat-eshell-update-semi-char-mode-map)
|
|
|
|
|
(eat-reload)))
|
2023-01-16 12:11:25 +06:00
|
|
|
|
:group 'eat-eshell)
|
|
|
|
|
|
2022-12-01 01:40:17 +06:00
|
|
|
|
(defcustom eat-enable-directory-tracking t
|
|
|
|
|
"Non-nil means do directory tracking.
|
|
|
|
|
|
|
|
|
|
When non-nil, Eat will track the working directory of program. You
|
|
|
|
|
need to configure the program to send current working directory
|
2022-12-01 02:01:11 +06:00
|
|
|
|
information. See Info node `(eat)Directory Tracking' for instructions
|
|
|
|
|
to setup your shell."
|
2022-12-01 01:40:17 +06:00
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'eat-ui
|
|
|
|
|
:group 'eat-eshell)
|
|
|
|
|
|
2022-12-06 12:23:28 +06:00
|
|
|
|
(defcustom eat-enable-shell-command-history t
|
|
|
|
|
"Non-nil means add shell commands to Emacs history.
|
|
|
|
|
|
|
|
|
|
When non-nil, any command you run in your shell will also appear in
|
|
|
|
|
the history of commands like `eat', `shell-command' and
|
|
|
|
|
`async-shell-command'."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'eat-ui
|
|
|
|
|
:group 'eat-eshell)
|
|
|
|
|
|
2022-12-06 21:30:01 +06:00
|
|
|
|
(defcustom eat-enable-shell-prompt-annotation t
|
|
|
|
|
"Non-nil means annotate shell prompt with the status of command.
|
|
|
|
|
|
|
|
|
|
When non-nil, display a mark in front of shell prompt describing the
|
|
|
|
|
status of the command executed in that prompt."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-shell-prompt-annotation-position 'left-margin
|
|
|
|
|
"The position where to display shell prompt annotation.
|
|
|
|
|
|
|
|
|
|
The value can be one of the following:
|
|
|
|
|
|
|
|
|
|
`left-margin' Use the left margin.
|
|
|
|
|
`right-margin' Use the right margin."
|
|
|
|
|
:type '(choice (const :tag "Left margin" left-margin)
|
|
|
|
|
(const :tag "Right margin" right-margin))
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-shell-prompt-annotation-running-margin-indicator "-"
|
|
|
|
|
"String in margin annotation to indicate the command is running."
|
|
|
|
|
:type 'string
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defface eat-shell-prompt-annotation-running
|
|
|
|
|
'((t :inherit compilation-info))
|
|
|
|
|
"Face used in annotation to indicate the command is running."
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-shell-prompt-annotation-success-margin-indicator "0"
|
|
|
|
|
"String in margin annotation to indicate the command has succeeded."
|
|
|
|
|
:type 'string
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defface eat-shell-prompt-annotation-success
|
|
|
|
|
'((t :inherit success))
|
|
|
|
|
"Face used in annotation to indicate the command has succeeded."
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-shell-prompt-annotation-failure-margin-indicator "X"
|
|
|
|
|
"String in margin annotation to indicate the command has failed."
|
|
|
|
|
:type 'string
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defface eat-shell-prompt-annotation-failure
|
|
|
|
|
'((t :inherit error))
|
|
|
|
|
"Face used in annotation to indicate the command has failed."
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
2022-12-07 11:06:44 +06:00
|
|
|
|
(defcustom eat-shell-prompt-annotation-correction-delay 0.1
|
|
|
|
|
"Seconds to wait before correcting shell prompt annotations.
|
2022-12-06 21:30:01 +06:00
|
|
|
|
|
2022-12-07 11:06:44 +06:00
|
|
|
|
Wait this many second after terminal update before correcting shell
|
2022-12-07 11:17:20 +06:00
|
|
|
|
prompt annotation."
|
|
|
|
|
:type 'number
|
2022-12-06 21:30:01 +06:00
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
2022-12-28 21:41:11 +06:00
|
|
|
|
(defcustom eat-exec-hook nil
|
|
|
|
|
"Hook run after `eat' executes a commamnd."
|
|
|
|
|
:type 'hook
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
2022-12-28 21:41:47 +06:00
|
|
|
|
(defcustom eat-eshell-exec-hook nil
|
|
|
|
|
"Hook run after `eat' executes a commamnd."
|
|
|
|
|
:type 'hook
|
|
|
|
|
:group 'eat-eshell)
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defconst eat--cursor-type-value-type
|
|
|
|
|
(let ((cur-type
|
|
|
|
|
'(choice
|
|
|
|
|
(const :tag "Frame default" t)
|
|
|
|
|
(const :tag "Filled box" box)
|
|
|
|
|
(cons :tag "Box with specified size" (const box) integer)
|
|
|
|
|
(const :tag "Hollow cursor" hollow)
|
|
|
|
|
(const :tag "Vertical bar" bar)
|
|
|
|
|
(cons :tag "Vertical bar with specified height" (const bar)
|
|
|
|
|
integer)
|
|
|
|
|
(const :tag "Horizontal bar" hbar)
|
|
|
|
|
(cons :tag "Horizontal bar with specified width"
|
|
|
|
|
(const hbar) integer)
|
|
|
|
|
(const :tag "None " nil))))
|
|
|
|
|
`(list
|
|
|
|
|
,cur-type
|
|
|
|
|
(choice
|
|
|
|
|
(const :tag "No blinking" nil)
|
|
|
|
|
(number :tag "Blinking frequency"))
|
|
|
|
|
,cur-type))
|
|
|
|
|
"Custom type specification for Eat's cursor type variables.")
|
|
|
|
|
|
|
|
|
|
(defcustom eat-default-cursor-type
|
|
|
|
|
`(,(default-value 'cursor-type) nil nil)
|
|
|
|
|
"Cursor to use in Eat buffer.
|
|
|
|
|
|
|
|
|
|
The value is a list of form (CURSOR-ON BLINKING-FREQUENCY CURSOR-OFF).
|
|
|
|
|
|
|
|
|
|
When the cursor is on, CURSOR-ON is used as `cursor-type', which see.
|
|
|
|
|
BLINKING-FREQUENCY is the blinking frequency of cursor's blinking.
|
|
|
|
|
When the cursor is off, CURSOR-OFF is used as `cursor-type'. This
|
|
|
|
|
should be nil when cursor is not blinking."
|
|
|
|
|
:type eat--cursor-type-value-type
|
|
|
|
|
:group 'eat-ui
|
2023-03-09 11:36:14 +06:00
|
|
|
|
:group 'eat-eshell)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defcustom eat-invisible-cursor-type '(nil nil nil)
|
|
|
|
|
"Invisible cursor to use in Eat buffer.
|
|
|
|
|
|
|
|
|
|
The value is a list of form (CURSOR-ON BLINKING-FREQUENCY CURSOR-OFF).
|
|
|
|
|
|
|
|
|
|
When the cursor is on, CURSOR-ON is used as `cursor-type', which see.
|
|
|
|
|
BLINKING-FREQUENCY is the blinking frequency of cursor's blinking.
|
|
|
|
|
When the cursor is off, CURSOR-OFF is used as `cursor-type'. This
|
|
|
|
|
should be nil when cursor is not blinking."
|
|
|
|
|
:type eat--cursor-type-value-type
|
|
|
|
|
:group 'eat-ui
|
2023-03-09 11:36:14 +06:00
|
|
|
|
:group 'eat-eshell)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defcustom eat-very-visible-cursor-type
|
|
|
|
|
`(,(default-value 'cursor-type) 2 hollow)
|
|
|
|
|
"Very visible cursor to use in Eat buffer.
|
|
|
|
|
|
|
|
|
|
When the cursor is invisible, the car of the value is used as
|
|
|
|
|
`cursor-type', which see. The cdr of the value, when non-nil, is the
|
|
|
|
|
blinking frequency of cursor."
|
|
|
|
|
:type eat--cursor-type-value-type
|
|
|
|
|
:group 'eat-ui
|
2023-03-09 11:36:14 +06:00
|
|
|
|
:group 'eat-eshell)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defcustom eat-minimum-latency 0.008
|
|
|
|
|
"Minimum display latency in seconds.
|
|
|
|
|
|
|
|
|
|
Lowering it too much may cause (or increase) flickering and decrease
|
|
|
|
|
performance due to too many redisplays. Increasing it too much will
|
|
|
|
|
cause the terminal to feel less responsive. Try to increase this
|
|
|
|
|
value if the terminal flickers."
|
|
|
|
|
:type 'number
|
|
|
|
|
:group 'eat-ui
|
2023-03-09 11:36:14 +06:00
|
|
|
|
:group 'eat-eshell)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defcustom eat-maximum-latency 0.033
|
|
|
|
|
"Minimum display latency in seconds.
|
|
|
|
|
|
|
|
|
|
Increasing it too much may make the terminal feel less responsive in
|
|
|
|
|
case of huge burst of output. Try to increase this value if the
|
|
|
|
|
terminal flickers. Try to lower the value if the terminal feels less
|
|
|
|
|
responsive."
|
|
|
|
|
:type 'number
|
|
|
|
|
:group 'eat-ui
|
2023-03-09 11:36:14 +06:00
|
|
|
|
:group 'eat-eshell)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defcustom eat-term-name #'eat-term-get-suitable-term-name
|
|
|
|
|
"Value for the `TERM' environment variable.
|
|
|
|
|
|
|
|
|
|
The value can also be a function. In that case, the function is
|
|
|
|
|
called without any argument and the return value is used as the value.
|
|
|
|
|
For example, this can set to `eat-term-get-suitable-term-name' to set
|
|
|
|
|
the value according to the number of colors supported by the current
|
|
|
|
|
display.
|
|
|
|
|
|
|
|
|
|
This value is used by terminal programs to identify the terminal."
|
|
|
|
|
:type '(choice
|
|
|
|
|
(string :tag "Value")
|
|
|
|
|
(const :tag "Automatic" eat-term-get-suitable-term-name)
|
|
|
|
|
(function :tag "Function"))
|
|
|
|
|
:group 'eat-term)
|
|
|
|
|
|
2022-12-04 18:43:06 +06:00
|
|
|
|
;; Upgrading Eat causes `eat-term-terminfo-directory' and
|
|
|
|
|
;; `eat-term-shell-integration-directory' to be outdated, so update it
|
|
|
|
|
;; if not modified by user (or something else).
|
2023-01-19 15:45:44 +06:00
|
|
|
|
(defvar eat--load-file-path nil
|
|
|
|
|
"Path to currently loaded Eat.")
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defvar eat--install-path nil
|
|
|
|
|
"Path to directory where Eat is installed.")
|
|
|
|
|
|
2022-12-21 01:02:03 +06:00
|
|
|
|
(defvar eat--terminfo-path nil
|
|
|
|
|
"Path to directory where Terminfo databases are installed.")
|
|
|
|
|
|
2022-12-07 13:17:37 +06:00
|
|
|
|
(defvar eat--shell-integration-path nil
|
|
|
|
|
"Path to directory where shell integration scripts are installed.")
|
|
|
|
|
|
2023-01-19 15:45:44 +06:00
|
|
|
|
(setq eat--load-file-path (or load-file-name buffer-file-name))
|
|
|
|
|
|
2022-12-21 01:02:03 +06:00
|
|
|
|
(setq eat--install-path
|
2023-01-19 15:45:44 +06:00
|
|
|
|
(copy-sequence (file-name-directory eat--load-file-path)))
|
2022-12-21 01:02:03 +06:00
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defvar eat-term-terminfo-directory)
|
2022-12-03 11:14:01 +06:00
|
|
|
|
(defvar eat-term-shell-integration-directory)
|
2022-12-21 01:02:03 +06:00
|
|
|
|
(let ((old-terminfo-path eat--terminfo-path)
|
2022-12-07 13:17:37 +06:00
|
|
|
|
(old-shell-integration-path eat--shell-integration-path))
|
2022-12-21 01:02:03 +06:00
|
|
|
|
(setq eat--terminfo-path
|
|
|
|
|
(expand-file-name "terminfo" eat--install-path))
|
2022-12-07 13:17:37 +06:00
|
|
|
|
(setq eat--shell-integration-path
|
|
|
|
|
(expand-file-name "integration" eat--install-path))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
2022-12-21 01:02:03 +06:00
|
|
|
|
(defcustom eat-term-terminfo-directory eat--terminfo-path
|
2022-12-03 11:14:01 +06:00
|
|
|
|
"Directory where required terminfo databases can be found.
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
This value is used by terminal programs to find the terminfo databases
|
|
|
|
|
that describe the capabilities of the terminal."
|
|
|
|
|
:type 'directory
|
|
|
|
|
:group 'eat-term)
|
|
|
|
|
|
2022-12-03 11:14:01 +06:00
|
|
|
|
(defcustom eat-term-shell-integration-directory
|
2022-12-07 13:17:37 +06:00
|
|
|
|
eat--shell-integration-path
|
2022-12-03 11:14:01 +06:00
|
|
|
|
"Directory where Eat shell integration scripts can be found.
|
|
|
|
|
|
|
|
|
|
This value is exposed to terminal programs as
|
|
|
|
|
`EAT_SHELL_INTEGRATION_DIR' environment variable."
|
|
|
|
|
:type 'directory
|
|
|
|
|
:group 'eat-ui
|
|
|
|
|
:group 'eat-eshell)
|
|
|
|
|
|
2022-12-21 01:02:03 +06:00
|
|
|
|
(when (eq eat-term-terminfo-directory old-terminfo-path)
|
|
|
|
|
(setq eat-term-terminfo-directory eat--terminfo-path))
|
2022-12-07 13:17:37 +06:00
|
|
|
|
(when (eq eat-term-shell-integration-directory
|
|
|
|
|
old-shell-integration-path)
|
|
|
|
|
(setq eat-term-shell-integration-directory
|
|
|
|
|
eat--shell-integration-path)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defcustom eat-term-inside-emacs (format "%s,eat" emacs-version)
|
|
|
|
|
"Value for the `INSIDE_EMACS' environment variable."
|
|
|
|
|
:type 'string
|
|
|
|
|
:group 'eat-term)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-enable-blinking-text nil
|
|
|
|
|
"Non-nil means enable blinking of text with blink attribute.
|
|
|
|
|
|
|
|
|
|
When non-nil, enable `eat-blink-mode' to enable blinking of text with
|
|
|
|
|
blink attribute by default. You manually toggle `eat-blink-mode' to
|
|
|
|
|
toggle this behavior buffer-locally."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'eat-ui
|
|
|
|
|
:group 'eat-eshell)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-slow-blink-frequency 2
|
|
|
|
|
"Frequency of blinking of slowly text.
|
|
|
|
|
|
|
|
|
|
This has an effect only if `eat-blink-mode' is enabled."
|
|
|
|
|
:type 'number
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-fast-blink-frequency 3
|
|
|
|
|
"Frequency of blinking of rapidly text.
|
|
|
|
|
|
|
|
|
|
This has an effect only if `eat-blink-mode' is enabled."
|
|
|
|
|
:type 'number
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-enable-alternative-display t
|
|
|
|
|
"Non-nil means enable alternative display.
|
|
|
|
|
|
|
|
|
|
Full screen programs often use alternative display to keep old
|
|
|
|
|
contents on display unaltered."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'eat-term)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-enable-mouse t
|
|
|
|
|
"Non-nil means enable mouse support.
|
|
|
|
|
|
|
|
|
|
When non-nil, terminal programs can receive mouse events from Emacs."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defcustom eat-input-chunk-size 1024
|
|
|
|
|
"Maximum size of chunk of data send at once.
|
|
|
|
|
|
|
|
|
|
Long inputs send to Eat processes are broken up into chunks of this
|
|
|
|
|
size.
|
|
|
|
|
|
|
|
|
|
If your process is choking on big inputs, try lowering the value."
|
|
|
|
|
:type 'integer
|
|
|
|
|
:group 'eat-ui)
|
|
|
|
|
|
|
|
|
|
(defface eat-term-bold '((t :inherit bold))
|
|
|
|
|
"Face used to render bold text."
|
|
|
|
|
:group 'eat-term)
|
|
|
|
|
|
|
|
|
|
(defface eat-term-faint '((t :weight light))
|
|
|
|
|
"Face used to render faint text."
|
|
|
|
|
:group 'eat-term)
|
|
|
|
|
|
|
|
|
|
(defface eat-term-italic '((t :inherit italic))
|
|
|
|
|
"Face used to render italic text."
|
|
|
|
|
:group 'eat-term)
|
|
|
|
|
|
|
|
|
|
(defface eat-term-slow-blink '((t :inverse-video t))
|
|
|
|
|
"Face used to render slowly blinking text."
|
|
|
|
|
:group 'eat-term)
|
|
|
|
|
|
|
|
|
|
(defface eat-term-fast-blink '((t :inverse-video t))
|
|
|
|
|
"Face used to render rapidly blinking text."
|
|
|
|
|
:group 'eat-term)
|
|
|
|
|
|
2022-11-30 17:26:26 +06:00
|
|
|
|
;; Define color faces.
|
|
|
|
|
(let ((face-counter 0))
|
|
|
|
|
(let ((colors '("black" "red" "green" "yellow" "blue" "magenta"
|
|
|
|
|
"cyan" "white")))
|
|
|
|
|
;; Basic colors.
|
|
|
|
|
(dolist (color colors)
|
|
|
|
|
(let ((face (intern (format "eat-term-color-%i" face-counter))))
|
|
|
|
|
(custom-declare-face
|
|
|
|
|
face `((t :inherit ,(intern (format "ansi-color-%s" color))))
|
|
|
|
|
(format "Face used to render %s color text." color)
|
|
|
|
|
:group 'eat-term)
|
|
|
|
|
(put (intern (format "eat-term-color-%s" color))
|
|
|
|
|
'face-alias face))
|
|
|
|
|
(cl-incf face-counter))
|
|
|
|
|
;; Bright colors.
|
|
|
|
|
(dolist (color colors)
|
|
|
|
|
(let ((face (intern (format "eat-term-color-%i" face-counter))))
|
|
|
|
|
(custom-declare-face
|
2022-12-04 16:42:34 +06:00
|
|
|
|
face `((t :inherit ,(intern (format "ansi-color-bright-%s"
|
|
|
|
|
color))))
|
2022-11-30 17:26:26 +06:00
|
|
|
|
(format "Face used to render bright %s color text." color)
|
|
|
|
|
:group 'eat-term)
|
|
|
|
|
(put (intern (format "eat-term-color-bright-%s" color))
|
|
|
|
|
'face-alias face))
|
|
|
|
|
(cl-incf face-counter)))
|
|
|
|
|
;; 256-colors.
|
|
|
|
|
(while (< face-counter 256)
|
|
|
|
|
(let ((color
|
|
|
|
|
(if (>= face-counter 232)
|
|
|
|
|
(format "#%06X"
|
|
|
|
|
(* #x010101
|
|
|
|
|
(+ 8 (* 10 (- face-counter 232)))))
|
|
|
|
|
(let ((col (- face-counter 16))
|
|
|
|
|
(res 0)
|
|
|
|
|
(frac (* 6 6)))
|
|
|
|
|
(while (<= 1 frac)
|
|
|
|
|
(setq res (* res #x000100))
|
|
|
|
|
(let ((color-num (mod (/ col frac) 6)))
|
|
|
|
|
(unless (zerop color-num)
|
|
|
|
|
(setq res (+ res #x37 (* #x28 color-num)))))
|
|
|
|
|
(setq frac (/ frac 6)))
|
|
|
|
|
(format "#%06X" res)))))
|
|
|
|
|
(custom-declare-face
|
|
|
|
|
(intern (format "eat-term-color-%i" face-counter))
|
|
|
|
|
`((t :foreground ,color :background ,color))
|
|
|
|
|
(format "Face used to render text with %i%s color of 256 color\
|
|
|
|
|
palette."
|
2022-12-08 17:36:54 +06:00
|
|
|
|
face-counter
|
|
|
|
|
(or (and (not (<= 11 (% face-counter 100) 13))
|
|
|
|
|
(nth (% face-counter 10)
|
|
|
|
|
'(nil "st" "nd" "rd")))
|
|
|
|
|
"th"))
|
2022-11-30 17:26:26 +06:00
|
|
|
|
:group 'eat-term))
|
|
|
|
|
(cl-incf face-counter)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defface eat-term-font-0 '((t))
|
2022-11-30 17:26:26 +06:00
|
|
|
|
"Default font."
|
|
|
|
|
:group 'eat-term)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(put 'eat-term-font-default 'face-alias 'eat-term-font-0)
|
|
|
|
|
|
2022-11-30 17:26:26 +06:00
|
|
|
|
;; Font faces, 1 to 9 (inclusive).
|
|
|
|
|
(cl-loop for counter from 1 to 9
|
|
|
|
|
do (custom-declare-face
|
2022-12-02 10:26:37 +06:00
|
|
|
|
(intern (format "eat-term-font-%i" counter)) '((t))
|
2022-11-30 17:26:26 +06:00
|
|
|
|
(format "Alternative font %i." counter)
|
|
|
|
|
:group 'eat-term))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;; Utility Functions.
|
|
|
|
|
|
|
|
|
|
(defun eat--t-goto-bol (&optional n)
|
|
|
|
|
"Go to the beginning of current line.
|
|
|
|
|
|
|
|
|
|
With optional argument N, go to the beginning of Nth next line if N is
|
|
|
|
|
positive, otherwise go to the beginning of -Nth previous line. If the
|
|
|
|
|
specified position is before `point-min' or after `point-max', go to
|
|
|
|
|
that point.
|
|
|
|
|
|
|
|
|
|
Return the number of lines moved.
|
|
|
|
|
|
|
|
|
|
Treat LINE FEED (?\\n) as the line delimiter."
|
|
|
|
|
;; TODO: Comment.
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(setq n (or n 0))
|
|
|
|
|
(cond ((> n 0)
|
|
|
|
|
(let ((moved 0))
|
|
|
|
|
(while (and (< (point) (point-max))
|
|
|
|
|
(< moved n))
|
|
|
|
|
(and (search-forward "\n" nil 'move)
|
|
|
|
|
(cl-incf moved)))
|
|
|
|
|
moved))
|
|
|
|
|
((<= n 0)
|
|
|
|
|
(let ((moved 1))
|
|
|
|
|
(while (and (or (= moved 1)
|
|
|
|
|
(< (point-min) (point)))
|
|
|
|
|
(< n moved))
|
|
|
|
|
(cl-decf moved)
|
|
|
|
|
(and (search-backward "\n" nil 'move)
|
|
|
|
|
(= moved n)
|
|
|
|
|
(goto-char (match-end 0))))
|
|
|
|
|
moved))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-goto-eol (&optional n)
|
|
|
|
|
"Go to the end of current line.
|
|
|
|
|
|
|
|
|
|
With optional argument N, go to the end of Nth next line if N is
|
|
|
|
|
positive, otherwise go to the end of -Nth previous line. If the
|
|
|
|
|
specified position is before `point-min' or after `point-max', go to
|
|
|
|
|
that point.
|
|
|
|
|
|
|
|
|
|
Return the number of lines moved.
|
|
|
|
|
|
|
|
|
|
Treat LINE FEED (?\\n) as the line delimiter."
|
|
|
|
|
;; TODO: Comment.
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(setq n (or n 0))
|
|
|
|
|
(cond ((>= n 0)
|
|
|
|
|
(let ((moved -1))
|
|
|
|
|
(while (and (or (= moved -1)
|
|
|
|
|
(< (point) (point-max)))
|
|
|
|
|
(< moved n))
|
|
|
|
|
(cl-incf moved)
|
|
|
|
|
(and (search-forward "\n" nil 'move)
|
|
|
|
|
(= moved n)
|
|
|
|
|
(goto-char (match-beginning 0))))
|
|
|
|
|
moved))
|
|
|
|
|
((< n 0)
|
|
|
|
|
(let ((moved 0))
|
|
|
|
|
(while (and (< (point-min) (point))
|
|
|
|
|
(< n moved))
|
|
|
|
|
(and (search-backward "\n" nil 'move)
|
|
|
|
|
(cl-decf moved)))
|
|
|
|
|
moved))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-bol (&optional n)
|
|
|
|
|
"Return the beginning of current line.
|
|
|
|
|
|
|
|
|
|
With optional argument N, return a cons cell whose car is the
|
|
|
|
|
beginning of Nth next line and cdr is N, if N is positive, otherwise
|
|
|
|
|
return a cons cell whose car is the beginning of -Nth previous line
|
|
|
|
|
and cdr is N. If the specified position is before `point-min' or
|
|
|
|
|
after `point-max', return a cons cell whose car is that point and cdr
|
|
|
|
|
is number of lines that point is away from current line.
|
|
|
|
|
|
|
|
|
|
Treat LINE FEED (?\\n) as the line delimiter."
|
|
|
|
|
;; Move to the beginning of line, record the point, and return that
|
|
|
|
|
;; point and the distance of that point from current line in lines.
|
|
|
|
|
(save-excursion
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
;; `let' is neccessary, we need to evaluate (point) after going to
|
|
|
|
|
;; `(eat--t-goto-bol N)'.
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(let ((moved (eat--t-goto-bol n)))
|
|
|
|
|
(cons (point) moved))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-eol (&optional n)
|
|
|
|
|
"Return the end of current line.
|
|
|
|
|
|
|
|
|
|
With optional argument N, return a cons cell whose car the end of Nth
|
|
|
|
|
next line and cdr is N, if N is positive, otherwise return a cons cell
|
|
|
|
|
whose car is the end of -Nth previous line and cdr in N. If the
|
|
|
|
|
specified position is before `point-min' or after `point-max', return
|
|
|
|
|
a cons cell whose car is that point and cdr is number of lines that
|
|
|
|
|
point is away from current line.
|
|
|
|
|
|
|
|
|
|
Treat LINE FEED (?\\n) as the line delimiter."
|
|
|
|
|
;; Move to the beginning of line, record the point, and return that
|
|
|
|
|
;; point and the distance of that point from current line in lines.
|
|
|
|
|
(save-excursion
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
;; `let' is neccessary, we need to evaluate (point) after going to
|
|
|
|
|
;; (eat--t-goto-eol N).
|
2022-11-28 12:40:19 +06:00
|
|
|
|
(let ((moved (eat--t-goto-eol n)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(cons (point) moved))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-col-motion (n)
|
|
|
|
|
"Move to Nth next column.
|
|
|
|
|
|
|
|
|
|
Go to Nth next column if N is positive, otherwise go to -Nth previous
|
|
|
|
|
column. If the specified position is before `point-min' or after
|
|
|
|
|
`point-max', go to that point.
|
|
|
|
|
|
|
|
|
|
Return the number of columns moved.
|
|
|
|
|
|
|
|
|
|
Assume all characters occupy a single column."
|
|
|
|
|
;; Record the current position.
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let ((start-pos (point)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Move to the new position.
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(cond ((> n 0)
|
|
|
|
|
(let ((eol (car (eat--t-eol)))
|
|
|
|
|
(pos (+ (point) n)))
|
|
|
|
|
(goto-char (min pos eol))))
|
|
|
|
|
((< n 0)
|
|
|
|
|
(let ((bol (car (eat--t-bol)))
|
|
|
|
|
(pos (+ (point) n)))
|
|
|
|
|
(goto-char (max pos bol)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Return the distance from the previous position.
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(- (point) start-pos)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-current-col ()
|
|
|
|
|
"Return the current column.
|
|
|
|
|
|
|
|
|
|
Assume all characters occupy a single column."
|
|
|
|
|
;; We assume that that all characters occupy a single column, so a
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
;; subtraction should work. For multi-column characters, we add
|
|
|
|
|
;; extra invisible spaces before the character to make it occupy as
|
|
|
|
|
;; many character is its width.
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(- (point) (car (eat--t-bol))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-goto-col (n)
|
|
|
|
|
"Go to column N.
|
|
|
|
|
|
|
|
|
|
Return the current column after moving point.
|
|
|
|
|
|
|
|
|
|
Assume all characters occupy a single column."
|
|
|
|
|
;; Move to column 0.
|
|
|
|
|
(eat--t-goto-bol)
|
|
|
|
|
;; Now the target column is N characters away.
|
|
|
|
|
(eat--t-col-motion n))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-repeated-insert (c n &optional face)
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
"Insert character C, N times, using face FACE, if given."
|
|
|
|
|
(insert (if face
|
|
|
|
|
(let ((str (make-string n c)))
|
|
|
|
|
(put-text-property 0 n 'face face str)
|
2022-12-22 20:27:50 +06:00
|
|
|
|
(put-text-property 0 n 'font-lock-face face str)
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
str)
|
|
|
|
|
;; Avoid the `let'.
|
|
|
|
|
(make-string n c))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-join-long-line (&optional limit)
|
|
|
|
|
"Join long line once, but don't try to go beyond LIMIT.
|
|
|
|
|
|
|
|
|
|
For example: \"*foo\\nbar\\nbaz\" is converted to \"foo*bar\\nbaz\",
|
|
|
|
|
where `*' indicates point."
|
|
|
|
|
;; Are we already at the end a part of a long line?
|
2022-12-15 13:52:08 +06:00
|
|
|
|
(unless (get-text-property (point) 'eat--t-wrap-line)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Find the next end of a part of a long line.
|
2022-12-15 13:52:08 +06:00
|
|
|
|
(goto-char (or (next-single-property-change
|
|
|
|
|
(point) 'eat--t-wrap-line nil limit)
|
|
|
|
|
limit (point-max))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Remove the newline.
|
|
|
|
|
(when (< (point) (or limit (point-max)))
|
|
|
|
|
(1value (cl-assert (1value (= (1value (char-after)) ?\n))))
|
|
|
|
|
(delete-char 1)))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-break-long-line (threshold)
|
|
|
|
|
"Break a line longer than THRESHOLD once.
|
|
|
|
|
|
|
|
|
|
For example: when THRESHOLD is 3, \"*foobarbaz\" is converted to
|
|
|
|
|
\"foo\\n*barbaz\", where `*' indicates point."
|
|
|
|
|
(let ((loop t))
|
|
|
|
|
;; Find a too long line.
|
|
|
|
|
(while (and loop (< (point) (point-max)))
|
|
|
|
|
;; Go to the threshold column.
|
|
|
|
|
(eat--t-goto-col threshold)
|
|
|
|
|
;; Are we at the end of line?
|
|
|
|
|
(if (eq (char-after) ?\n)
|
|
|
|
|
;; We are already at the end of line, so move to the next
|
|
|
|
|
;; line and start from the beginning.
|
|
|
|
|
(forward-char)
|
|
|
|
|
;; The next character is not a newline, so we must be at a
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
;; long line, or we are the end of the accessible part of the
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; buffer. Whatever the case, we break the loop, and if it is
|
|
|
|
|
;; a long line, we break the line.
|
|
|
|
|
(setq loop nil)
|
|
|
|
|
(unless (= (point) (point-max))
|
|
|
|
|
(insert-before-markers
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
#("\n" 0 1 (eat--t-wrap-line t))))))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;; Emulator.
|
|
|
|
|
|
|
|
|
|
(cl-defstruct (eat--t-cur
|
|
|
|
|
(:constructor eat--t-make-cur)
|
|
|
|
|
(:copier eat--t-copy-cur))
|
|
|
|
|
"Structure describing cursor position."
|
|
|
|
|
(position nil :documentation "Position of cursor.")
|
|
|
|
|
(y 1 :documentation "Y coordinate of cursor.")
|
|
|
|
|
(x 1 :documentation "X coordinate of cursor."))
|
|
|
|
|
|
|
|
|
|
(cl-defstruct (eat--t-disp
|
|
|
|
|
(:constructor eat--t-make-disp)
|
|
|
|
|
(:copier eat--t-copy-disp))
|
|
|
|
|
"Structure describing the display."
|
|
|
|
|
(begin nil :documentation "Beginning of visible display.")
|
|
|
|
|
(width 80 :documentation "Width of display.")
|
|
|
|
|
(height 24 :documentation "Height of display.")
|
|
|
|
|
(cursor nil :documentation "Cursor.")
|
|
|
|
|
(saved-cursor
|
|
|
|
|
(1value (eat--t-make-cur))
|
|
|
|
|
:documentation "Saved cursor.")
|
|
|
|
|
(old-begin
|
|
|
|
|
nil
|
|
|
|
|
:documentation
|
|
|
|
|
"Beginning of visible display during last Eat redisplay."))
|
|
|
|
|
|
|
|
|
|
(cl-defstruct (eat--t-face
|
|
|
|
|
(:constructor eat--t-make-face)
|
|
|
|
|
(:copier eat--t-copy-face))
|
|
|
|
|
"Structure describing the display attributes to use."
|
|
|
|
|
(face nil :documentation "Face to use.")
|
|
|
|
|
(fg nil :documentation "Foreground color.")
|
|
|
|
|
(bg nil :documentation "Background color.")
|
|
|
|
|
(intensity nil :documentation "Intensity face, or nil.")
|
|
|
|
|
(italic nil :documentation "Non-nil means use italic face.")
|
|
|
|
|
(underline nil :documentation "Non-nil means underline text.")
|
|
|
|
|
(underline-color nil :documentation "Underline color.")
|
|
|
|
|
(crossed nil :documentation "Non-nil means strike-through text.")
|
|
|
|
|
(conceal nil :documentation "Non-nil means invisible text.")
|
|
|
|
|
(inverse nil :documentation "Non-nil means inverse colors.")
|
|
|
|
|
(blink nil :documentation "Blink face, or nil.")
|
|
|
|
|
(font 'eat-term-font-0 :documentation "Current font face."))
|
|
|
|
|
|
|
|
|
|
(cl-defstruct (eat--t-term
|
|
|
|
|
(:constructor eat--t-make-term)
|
|
|
|
|
(:copier eat--t-copy-term))
|
|
|
|
|
"Structure describing a terminal."
|
|
|
|
|
(buffer nil :documentation "The buffer of terminal.")
|
|
|
|
|
(begin nil :documentation "Beginning of terminal.")
|
|
|
|
|
(end nil :documentation "End of terminal area.")
|
|
|
|
|
(title "" :documentation "The title of the terminal.")
|
2022-12-01 01:40:17 +06:00
|
|
|
|
(cwd
|
2022-12-07 00:11:29 +06:00
|
|
|
|
(cons (system-name) default-directory)
|
2022-12-01 01:40:17 +06:00
|
|
|
|
:documentation "The working directory of the terminal.")
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(bell-fn
|
|
|
|
|
(1value #'ignore)
|
|
|
|
|
:documentation "Function to ring the bell.")
|
|
|
|
|
(input-fn
|
|
|
|
|
(1value #'ignore)
|
|
|
|
|
:documentation "Function to send input.")
|
|
|
|
|
(set-cursor-fn
|
|
|
|
|
(1value #'ignore)
|
|
|
|
|
:documentation "Function to set cursor.")
|
|
|
|
|
(manipulate-selection-fn
|
|
|
|
|
(1value #'ignore)
|
|
|
|
|
:documentation "Function to manipulate selection.")
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
(grab-mouse-fn
|
|
|
|
|
(1value #'ignore)
|
|
|
|
|
:documentation "Function to grab mouse.")
|
|
|
|
|
(set-focus-ev-mode-fn
|
|
|
|
|
(1value #'ignore)
|
|
|
|
|
:documentation "Function to set focus event mode.")
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(set-title-fn
|
|
|
|
|
(1value #'ignore)
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
:documentation "Function to set the title.")
|
2022-12-01 01:40:17 +06:00
|
|
|
|
(set-cwd-fn
|
|
|
|
|
(1value #'ignore)
|
|
|
|
|
:documentation "Function to set the current working directory.")
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
(prompt-start-fn
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(1value #'ignore)
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
:documentation "Function to call when prompt starts.")
|
|
|
|
|
(prompt-end-fn
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(1value #'ignore)
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
:documentation "Function to call when prompt ends.")
|
|
|
|
|
(cont-prompt-start-fn
|
|
|
|
|
(1value #'ignore)
|
|
|
|
|
:documentation "Function to call when prompt starts.")
|
|
|
|
|
(cont-prompt-end-fn
|
|
|
|
|
(1value #'ignore)
|
|
|
|
|
:documentation "Function to call when prompt ends.")
|
|
|
|
|
(set-cmd-fn
|
|
|
|
|
(1value #'ignore)
|
|
|
|
|
:documentation "Function to set the command being executed.")
|
|
|
|
|
(cmd-start-fn
|
|
|
|
|
(1value #'ignore)
|
|
|
|
|
:documentation "Function to call just before a command is run.")
|
|
|
|
|
(cmd-finish-fn
|
|
|
|
|
(1value #'ignore)
|
|
|
|
|
:documentation "Function to call after a command has finished.")
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(parser-state nil :documentation "State of parser.")
|
|
|
|
|
(scroll-begin 1 :documentation "First line of scroll region.")
|
|
|
|
|
(scroll-end 24 :documentation "Last line of scroll region.")
|
|
|
|
|
(display nil :documentation "The display.")
|
|
|
|
|
(main-display nil :documentation "Main display.
|
|
|
|
|
|
|
|
|
|
Nil when not in alternative display mode.")
|
|
|
|
|
(face
|
|
|
|
|
(1value (eat--t-make-face))
|
|
|
|
|
:documentation "Display attributes.")
|
|
|
|
|
(auto-margin t :documentation "State of auto margin mode.")
|
|
|
|
|
(ins-mode nil :documentation "State of insert mode.")
|
|
|
|
|
(charset
|
|
|
|
|
(copy-tree '(g0 . ((g0 . us-ascii)
|
|
|
|
|
(g1 . us-ascii)
|
|
|
|
|
(g2 . us-ascii)
|
|
|
|
|
(g3 . us-ascii))))
|
|
|
|
|
:documentation "Current character set.")
|
|
|
|
|
(cur-state :default :documentation "Current state of cursor.")
|
|
|
|
|
(cur-blinking-p nil :documentation "Is the cursor blinking?")
|
|
|
|
|
(saved-face
|
|
|
|
|
(1value (eat--t-make-face))
|
|
|
|
|
:documentation "Saved SGR attributes.")
|
|
|
|
|
(bracketed-yank nil :documentation "State of bracketed yank mode.")
|
|
|
|
|
(keypad-mode nil :documentation "State of keypad mode.")
|
|
|
|
|
(mouse-mode nil :documentation "Current mouse mode.")
|
|
|
|
|
(mouse-pressed nil :documentation "Pressed mouse buttons.")
|
|
|
|
|
(mouse-encoding nil :documentation "Current mouse event encoding.")
|
|
|
|
|
(focus-event-mode nil :documentation "Whether to send focus event.")
|
|
|
|
|
(cut-buffers
|
2023-03-28 13:58:43 +06:00
|
|
|
|
(1value (make-vector 8 nil))
|
2022-12-10 02:14:28 +06:00
|
|
|
|
:documentation "Cut buffers.")
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
;; NOTE: Change the default value of parameters when changing this.
|
|
|
|
|
(bold-face 'eat-term-bold :documentation "Face for bold text.")
|
|
|
|
|
(faint-face 'eat-term-faint :documentation "Face for faint text.")
|
|
|
|
|
(italic-face 'eat-term-italic :documentation "Face for slant text.")
|
|
|
|
|
(slow-blink-face 'eat-term-slow-blink :documentation "Slow blink.")
|
|
|
|
|
(fast-blink-face 'eat-term-fast-blink :documentation "Fast blink.")
|
|
|
|
|
(color-faces
|
|
|
|
|
(copy-sequence
|
|
|
|
|
(eval-when-compile
|
|
|
|
|
(vconcat
|
|
|
|
|
(cl-loop for i from 0 to 255
|
|
|
|
|
collect (intern (format "eat-term-color-%i" i))))))
|
|
|
|
|
:documentation "Faces for colors.")
|
|
|
|
|
(font-faces
|
|
|
|
|
(copy-sequence
|
|
|
|
|
(eval-when-compile
|
|
|
|
|
(vconcat
|
|
|
|
|
(cl-loop for i from 0 to 9
|
|
|
|
|
collect (intern (format "eat-term-font-%i" i))))))
|
|
|
|
|
:documentation "Faces for fonts.")
|
|
|
|
|
(params
|
|
|
|
|
(copy-hash-table
|
|
|
|
|
(eval-when-compile
|
|
|
|
|
(let ((tbl (make-hash-table :test 'eq)))
|
|
|
|
|
(puthash 'bold-face 'eat-term-bold tbl)
|
|
|
|
|
(puthash 'faint-face 'eat-term-faint tbl)
|
|
|
|
|
(puthash 'italic-face 'eat-term-italic tbl)
|
|
|
|
|
(puthash 'slow-blink-face 'eat-term-slow-blink tbl)
|
|
|
|
|
(puthash 'fast-blink-face 'eat-term-fast-blink tbl)
|
|
|
|
|
(cl-loop
|
|
|
|
|
for i from 0 to 255
|
|
|
|
|
do (puthash (intern (format "color-%i-face" i))
|
|
|
|
|
(intern (format "eat-term-color-%i" i)) tbl))
|
|
|
|
|
(cl-loop
|
|
|
|
|
for i from 0 to 9
|
|
|
|
|
do (puthash (intern (format "font-%i-face" i))
|
|
|
|
|
(intern (format "eat-term-font-%i" i)) tbl))
|
|
|
|
|
tbl)))
|
|
|
|
|
:documentation "Alist of terminal parameters."))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defvar eat--t-term nil
|
|
|
|
|
"The current terminal.
|
|
|
|
|
|
|
|
|
|
Don't `set' it, bind it to a value with `let'.")
|
|
|
|
|
|
|
|
|
|
(defun eat--t-reset ()
|
|
|
|
|
"Reset terminal."
|
2022-11-28 12:40:19 +06:00
|
|
|
|
(let ((disp (eat--t-term-display eat--t-term)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Reset most of the things to their respective default values.
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term) nil)
|
|
|
|
|
(setf (eat--t-disp-begin disp) (point-min-marker))
|
|
|
|
|
(setf (eat--t-disp-old-begin disp) (point-min-marker))
|
|
|
|
|
(setf (eat--t-disp-cursor disp)
|
|
|
|
|
(eat--t-make-cur :position (point-min-marker)))
|
|
|
|
|
(setf (eat--t-disp-saved-cursor disp) (eat--t-make-cur))
|
|
|
|
|
(setf (eat--t-term-scroll-begin eat--t-term) 1)
|
|
|
|
|
(setf (eat--t-term-scroll-end eat--t-term)
|
|
|
|
|
(eat--t-disp-height disp))
|
|
|
|
|
(setf (eat--t-term-main-display eat--t-term) nil)
|
|
|
|
|
(setf (eat--t-term-face eat--t-term) (eat--t-make-face))
|
|
|
|
|
(setf (eat--t-term-auto-margin eat--t-term) t)
|
|
|
|
|
(setf (eat--t-term-ins-mode eat--t-term) nil)
|
|
|
|
|
(setf (eat--t-term-charset eat--t-term)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
'(g0 (g0 . us-ascii)
|
|
|
|
|
(g1 . dec-line-drawing)
|
|
|
|
|
(g2 . dec-line-drawing)
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(g3 . dec-line-drawing)))
|
|
|
|
|
(setf (eat--t-term-saved-face eat--t-term) (eat--t-make-face))
|
|
|
|
|
(setf (eat--t-term-bracketed-yank eat--t-term) nil)
|
|
|
|
|
(setf (eat--t-term-cur-state eat--t-term) :default)
|
|
|
|
|
(setf (eat--t-term-cur-blinking-p eat--t-term) nil)
|
|
|
|
|
(setf (eat--t-term-title eat--t-term) "")
|
|
|
|
|
(setf (eat--t-term-keypad-mode eat--t-term) nil)
|
|
|
|
|
(setf (eat--t-term-mouse-mode eat--t-term) nil)
|
|
|
|
|
(setf (eat--t-term-mouse-encoding eat--t-term) nil)
|
|
|
|
|
(setf (eat--t-term-focus-event-mode eat--t-term) nil)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Clear everything.
|
|
|
|
|
(delete-region (point-min) (point-max))
|
|
|
|
|
;; Inform the UI about our new state.
|
|
|
|
|
(funcall (eat--t-term-grab-mouse-fn eat--t-term) eat--t-term nil)
|
|
|
|
|
(funcall (eat--t-term-set-focus-ev-mode-fn eat--t-term)
|
|
|
|
|
eat--t-term nil)
|
|
|
|
|
(funcall (eat--t-term-set-title-fn eat--t-term) eat--t-term "")
|
|
|
|
|
(funcall (eat--t-term-set-cursor-fn eat--t-term) eat--t-term
|
|
|
|
|
:default)))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-cur-right (&optional n)
|
|
|
|
|
"Move cursor N columns right.
|
|
|
|
|
|
|
|
|
|
N default to 1. If N is out of range, place cursor at the edge of
|
|
|
|
|
display."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
;; If N is less than 1, set N to 1. If N is more than the number
|
|
|
|
|
;; of available columns on the right side, set N to the maximum
|
|
|
|
|
;; possible value.
|
|
|
|
|
(setq n (min (- (eat--t-disp-width disp) (eat--t-cur-x cursor))
|
|
|
|
|
(max (or n 1) 1)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; N is non-zero in most cases, except at the edge of display.
|
|
|
|
|
(unless (zerop n)
|
|
|
|
|
;; Move to the Nth next column, use spaces to reach that column
|
|
|
|
|
;; if needed.
|
2022-11-27 00:21:56 +06:00
|
|
|
|
(eat--t-repeated-insert ?\s (- n (eat--t-col-motion n)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(cl-incf (eat--t-cur-x cursor) n))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-cur-left (&optional n)
|
|
|
|
|
"Move cursor N columns left.
|
|
|
|
|
|
|
|
|
|
N default to 1. If N is out of range, place cursor at the edge of
|
|
|
|
|
display."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
;; If N is less than 1, set N to 1. If N is more than the number
|
|
|
|
|
;; of available columns on the left side, set N to the maximum
|
|
|
|
|
;; possible value.
|
|
|
|
|
(setq n (min (1- (eat--t-cur-x cursor)) (max (or n 1) 1)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; N is non-zero in most cases, except at the edge of display.
|
|
|
|
|
(unless (zerop n)
|
|
|
|
|
;; Move to the Nth previous column.
|
|
|
|
|
(cl-assert (1value (>= (eat--t-current-col) n)))
|
|
|
|
|
(backward-char n)
|
|
|
|
|
(cl-decf (eat--t-cur-x cursor) n))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-cur-horizontal-abs (&optional n)
|
|
|
|
|
"Move cursor to Nth column on current line.
|
|
|
|
|
|
|
|
|
|
N default to 1. If N is out of range, place cursor at the edge of
|
|
|
|
|
display."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
;; If N is out of range, bring it within the bounds of range.
|
|
|
|
|
(setq n (min (max (or n 1) 1) (eat--t-disp-width disp)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Depending on the current position of cursor, move right or
|
|
|
|
|
;; left.
|
|
|
|
|
(cond ((< (eat--t-cur-x cursor) n)
|
|
|
|
|
(eat--t-cur-right (- n (eat--t-cur-x cursor))))
|
|
|
|
|
((< n (eat--t-cur-x cursor))
|
|
|
|
|
(eat--t-cur-left (- (eat--t-cur-x cursor) n))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-beg-of-next-line (n)
|
|
|
|
|
"Move to beginning of Nth next line."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
;; If N is less than 1, set N to 1. If N is more than the number
|
|
|
|
|
;; of available lines below, set N to the maximum possible value.
|
|
|
|
|
(setq n (min (- (eat--t-disp-height disp) (eat--t-cur-y cursor))
|
|
|
|
|
(max (or n 1) 1)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; N is non-zero in most cases, except at the edge of display.
|
|
|
|
|
;; Whatever the case, we move to the beginning of line.
|
|
|
|
|
(if (zerop n)
|
|
|
|
|
(1value (eat--t-goto-bol))
|
|
|
|
|
;; Move to the Nth next line, use newlines to reach that line if
|
|
|
|
|
;; needed.
|
|
|
|
|
(eat--t-repeated-insert ?\n (- n (eat--t-goto-bol n)))
|
|
|
|
|
(cl-incf (eat--t-cur-y cursor) n))
|
|
|
|
|
(1value (setf (eat--t-cur-x cursor) 1))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-beg-of-prev-line (n)
|
|
|
|
|
"Move to beginning of Nth previous line."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
;; If N is less than 1, set N to 1. If N is more than the number
|
|
|
|
|
;; of available lines above, set N to the maximum possible value.
|
|
|
|
|
(setq n (min (1- (eat--t-cur-y cursor)) (max (or n 1) 1)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Move to the beginning Nth previous line. Even if there are no
|
|
|
|
|
;; line above, move to the beginning of the line.
|
|
|
|
|
(eat--t-goto-bol (- n))
|
|
|
|
|
(cl-decf (eat--t-cur-y cursor) n)
|
|
|
|
|
(1value (setf (eat--t-cur-x cursor) 1))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-cur-down (&optional n)
|
|
|
|
|
"Move cursor N lines down.
|
|
|
|
|
|
|
|
|
|
N default to 1. If N is out of range, place cursor at the edge of
|
|
|
|
|
display."
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let ((x (eat--t-cur-x (eat--t-disp-cursor
|
|
|
|
|
(eat--t-term-display eat--t-term)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Move to the beginning of target line.
|
|
|
|
|
(eat--t-beg-of-next-line n)
|
|
|
|
|
;; If the cursor wasn't at column one, move the cursor to the
|
|
|
|
|
;; cursor to that column.
|
|
|
|
|
(unless (= x 1)
|
|
|
|
|
(eat--t-cur-right (1- x)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-cur-up (&optional n)
|
|
|
|
|
"Move cursor N lines up.
|
|
|
|
|
|
|
|
|
|
N default to 1. If N is out of range, place cursor at the edge of
|
|
|
|
|
display."
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let ((x (eat--t-cur-x (eat--t-disp-cursor
|
|
|
|
|
(eat--t-term-display eat--t-term)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Move to the beginning of target line.
|
|
|
|
|
(eat--t-beg-of-prev-line n)
|
|
|
|
|
;; If the cursor wasn't at column one, move the cursor to the
|
|
|
|
|
;; cursor to that column.
|
|
|
|
|
(unless (= x 1)
|
|
|
|
|
(eat--t-cur-right (1- x)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-cur-vertical-abs (&optional n)
|
|
|
|
|
"Move cursor to Nth line on display.
|
|
|
|
|
|
|
|
|
|
N default to 1. If N is out of range, place cursor at the edge of
|
|
|
|
|
display."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
;; If N is out of range, bring it within the bounds of range.
|
|
|
|
|
(setq n (min (max (or n 1) 1) (eat--t-disp-height disp)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Depending on the current position of cursor, move downward or
|
|
|
|
|
;; upward.
|
|
|
|
|
(cond ((< (eat--t-cur-y cursor) n)
|
|
|
|
|
(eat--t-cur-down (- n (eat--t-cur-y cursor))))
|
|
|
|
|
((< n (eat--t-cur-y cursor))
|
|
|
|
|
(eat--t-cur-up (- (eat--t-cur-y cursor) n))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-scroll-up (&optional n as-side-effect)
|
|
|
|
|
"Scroll up N lines, preserving cursor position.
|
|
|
|
|
|
|
|
|
|
N default to 1. By default, don't change current line and current
|
|
|
|
|
column, but if AS-SIDE-EFFECT is given and non-nil, assume that
|
|
|
|
|
scrolling is triggered as a side effect of some other control function
|
|
|
|
|
and don't move the point relative to the text and change current line
|
|
|
|
|
accordingly."
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(scroll-begin (eat--t-term-scroll-begin eat--t-term))
|
|
|
|
|
(scroll-end (eat--t-term-scroll-end eat--t-term)))
|
|
|
|
|
;; N shouldn't be more more than the number of lines in scroll
|
|
|
|
|
;; region.
|
|
|
|
|
(setq n (min (max (or n 1) 0) (1+ (- scroll-end scroll-begin))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Make sure that N is positive.
|
|
|
|
|
(unless (zerop n)
|
|
|
|
|
;; Try to not point relative to the text.
|
|
|
|
|
(save-excursion
|
|
|
|
|
(goto-char (eat--t-disp-begin disp))
|
|
|
|
|
;; Move to the beginning of scroll region.
|
|
|
|
|
(eat--t-goto-bol (1- scroll-begin))
|
|
|
|
|
;; If the first line on display isn't in scroll region or
|
|
|
|
|
;; if this is the alternative display, delete text.
|
|
|
|
|
(if (or (eat--t-term-main-display eat--t-term)
|
|
|
|
|
(> scroll-begin 1))
|
|
|
|
|
(delete-region (point) (car (eat--t-bol n)))
|
|
|
|
|
;; Otherwise, send the text to the scrollback area by
|
|
|
|
|
;; advancing the display beginning marker.
|
|
|
|
|
(eat--t-goto-bol n)
|
|
|
|
|
;; Make sure we're at the beginning of a line, because we
|
|
|
|
|
;; might be at `point-max'.
|
|
|
|
|
(unless (or (= (point) (point-min))
|
|
|
|
|
(= (char-before) ?\n))
|
|
|
|
|
(insert ?\n))
|
|
|
|
|
(set-marker (eat--t-disp-begin disp) (point)))
|
|
|
|
|
;; Is the last line on display in scroll region?
|
2022-12-17 16:12:17 +06:00
|
|
|
|
(when (< scroll-end (eat--t-disp-width disp))
|
|
|
|
|
;; No, it isn't.
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Go to the end of scroll region (before deleting or moving
|
|
|
|
|
;; texts).
|
|
|
|
|
(eat--t-goto-bol (- (1+ (- scroll-end scroll-begin)) n))
|
|
|
|
|
;; If there is anything after the scroll region, insert
|
|
|
|
|
;; newlines to keep that text unmoved.
|
|
|
|
|
(when (< (point) (point-max))
|
|
|
|
|
(eat--t-repeated-insert ?\n n))))
|
|
|
|
|
;; Recalculate point if needed.
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let* ((cursor (eat--t-disp-cursor disp))
|
|
|
|
|
(recalc-point
|
|
|
|
|
(<= scroll-begin (eat--t-cur-y cursor) scroll-end)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; If recalc-point is non-nil, and AS-SIDE-EFFECT is non-nil,
|
|
|
|
|
;; update cursor position so that it is unmoved relative to
|
|
|
|
|
;; surrounding text and reconsider point recalculation.
|
|
|
|
|
(when (and recalc-point as-side-effect)
|
|
|
|
|
(setq recalc-point (< (- (eat--t-cur-y cursor) n)
|
|
|
|
|
scroll-begin))
|
|
|
|
|
(setf (eat--t-cur-y cursor)
|
|
|
|
|
(max (- (eat--t-cur-y cursor) n) scroll-begin)))
|
|
|
|
|
(when recalc-point
|
|
|
|
|
;; Recalculate point.
|
|
|
|
|
(let ((y (eat--t-cur-y cursor))
|
|
|
|
|
(x (eat--t-cur-x cursor)))
|
|
|
|
|
(eat--t-goto 1 1)
|
|
|
|
|
(eat--t-goto y x)))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-scroll-down (&optional n)
|
|
|
|
|
"Scroll down N lines, preserving cursor position.
|
|
|
|
|
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
N defaults to 1."
|
|
|
|
|
(let ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(scroll-begin (eat--t-term-scroll-begin eat--t-term))
|
|
|
|
|
(scroll-end (eat--t-term-scroll-end eat--t-term)))
|
|
|
|
|
;; N shouldn't be more more than the number of lines in scroll
|
|
|
|
|
;; region.
|
|
|
|
|
(setq n (min (max (or n 1) 0) (1+ (- scroll-end scroll-begin))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Make sure that N is positive.
|
|
|
|
|
(unless (zerop n)
|
|
|
|
|
;; Move to the beginning of scroll region.
|
|
|
|
|
(goto-char (eat--t-disp-begin disp))
|
|
|
|
|
(eat--t-goto-bol (1- scroll-begin))
|
|
|
|
|
;; Insert newlines to push text downwards.
|
|
|
|
|
(eat--t-repeated-insert ?\n n)
|
|
|
|
|
;; Go to the end scroll region (after inserting newlines).
|
|
|
|
|
(eat--t-goto-eol (- (1+ (- scroll-end scroll-begin)) (1+ n)))
|
|
|
|
|
;; Delete the text that was pushed out of scroll region.
|
|
|
|
|
(when (< (point) (point-max))
|
|
|
|
|
(delete-region (point) (car (eat--t-eol n))))
|
|
|
|
|
;; The cursor mustn't move, so we have to recalculate point.
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let* ((cursor (eat--t-disp-cursor disp))
|
|
|
|
|
(y (eat--t-cur-y cursor))
|
|
|
|
|
(x (eat--t-cur-x cursor)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat--t-goto 1 1)
|
|
|
|
|
(eat--t-goto y x)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-goto (&optional y x)
|
|
|
|
|
"Go to Xth column of Yth line of display.
|
|
|
|
|
|
|
|
|
|
Y and X default to 1. Y and X are one-based. If Y and/or X are out
|
|
|
|
|
of range, place cursor at the edge of display."
|
|
|
|
|
;; Important special case: if Y and X are both one, move to the
|
|
|
|
|
;; display beginning.
|
|
|
|
|
(if (and (or (not y) (eql y 1))
|
|
|
|
|
(or (not x) (eql x 1)))
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
(goto-char (eat--t-disp-begin disp))
|
Combine multiple setq/setf/setq-local into one
* eat.el (eat--t-reset, eat--t-goto, eat--t-write)
(eat--t-save-cur, eat--t-enable-alt-disp)
(eat--t-change-scroll-region, eat--t-set-sgr-params)
(eat--t-manipulate-selection, eat--t-handle-output)
(eat--t-resize, eat--flip-slow-blink-state)
(eat--flip-fast-blink-state, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-local-mode)
(eat--eshell-exec-visual, eat--trace-exec)
(eat--eshell-trace-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Combine multiple setq/setf/setq-local into one wherever
possible.
2022-11-28 21:54:55 +06:00
|
|
|
|
(1value (setf (eat--t-cur-y cursor) 1
|
|
|
|
|
(eat--t-cur-x cursor) 1)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Move to column one, go to Yth line and move to Xth column.
|
|
|
|
|
;; REVIEW: We move relative to cursor position, which faster for
|
|
|
|
|
;; positions near the point (usually the case), but slower for
|
|
|
|
|
;; positions far away from the point. There are only two cursor
|
|
|
|
|
;; positions whose exact position is known beforehand, the cursor
|
|
|
|
|
;; (whose position is (point)) and (1, 1) (the display beginning).
|
|
|
|
|
;; There are almost always some points which are at more distance
|
|
|
|
|
;; from current position than from the display beginning (the only
|
|
|
|
|
;; exception is when the cursor is at the display beginning). So
|
|
|
|
|
;; first moving to the display beginning and then moving to those
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
;; point will be faster than moving from cursor (except a tiny
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; (perhaps negligible) overhead of `goto-char'). What we don't
|
|
|
|
|
;; have is a formula the calculate the distance between two
|
|
|
|
|
;; positions.
|
|
|
|
|
(eat--t-cur-horizontal-abs 1)
|
|
|
|
|
(eat--t-cur-vertical-abs y)
|
|
|
|
|
(eat--t-cur-horizontal-abs x)))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-enable-auto-margin ()
|
|
|
|
|
"Enable automatic margin."
|
|
|
|
|
;; Set the automatic margin flag to t, the rest of code will take
|
|
|
|
|
;; care of the effects.
|
|
|
|
|
(1value (setf (eat--t-term-auto-margin eat--t-term) t)))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-disable-auto-margin ()
|
|
|
|
|
"Disable automatic margin."
|
|
|
|
|
;; Set the automatic margin flag to nil, the rest of code will take
|
|
|
|
|
;; care of the effects.
|
|
|
|
|
(1value (setf (eat--t-term-auto-margin eat--t-term) nil)))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-set-charset (slot charset)
|
|
|
|
|
"SLOT's character set to CHARSET."
|
|
|
|
|
(setf (alist-get slot (cdr (eat--t-term-charset eat--t-term)))
|
|
|
|
|
charset))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-change-charset (charset)
|
|
|
|
|
"Change character set to CHARSET.
|
|
|
|
|
|
|
|
|
|
CHARSET should be one of `g0', `g1', `g2' and `g3'."
|
2022-11-28 22:13:06 +06:00
|
|
|
|
(cl-assert (memq charset '(g0 g1 g2 g3)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(setf (car (eat--t-term-charset eat--t-term)) charset))
|
|
|
|
|
|
2022-11-28 03:01:45 +06:00
|
|
|
|
(defun eat--t-move-before-to-safe ()
|
|
|
|
|
"Move to a safe position before point. Return how much moved.
|
|
|
|
|
|
|
|
|
|
If the current position is safe, do nothing and return 0.
|
|
|
|
|
|
|
|
|
|
Safe position is the position that's not on a multi-column wide
|
|
|
|
|
character or its the internal invisible spaces."
|
|
|
|
|
(if (and (not (bobp))
|
|
|
|
|
;; Is the current position unsafe?
|
|
|
|
|
(get-text-property (1- (point)) 'eat--t-invisible-space))
|
|
|
|
|
(let ((start-pos (point)))
|
|
|
|
|
;; Move to the safe position.
|
2022-12-15 13:52:08 +06:00
|
|
|
|
(goto-char (or (previous-single-property-change
|
|
|
|
|
(point) 'eat--t-invisible-space)
|
|
|
|
|
(point-min)))
|
2022-11-28 03:01:45 +06:00
|
|
|
|
(cl-assert
|
|
|
|
|
(1value (or (bobp)
|
|
|
|
|
(null (get-text-property
|
|
|
|
|
(1- (point)) 'eat--t-invisible-space)))))
|
|
|
|
|
(- start-pos (point)))
|
|
|
|
|
0))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-make-pos-safe ()
|
|
|
|
|
"If the position isn't safe, make it safe by replacing with spaces."
|
|
|
|
|
(let ((moved (eat--t-move-before-to-safe)))
|
|
|
|
|
(unless (zerop moved)
|
|
|
|
|
(let ((width (get-text-property
|
|
|
|
|
(point) 'eat--t-char-width)))
|
|
|
|
|
(cl-assert width)
|
|
|
|
|
(delete-region (point) (+ (point) width))
|
|
|
|
|
(eat--t-repeated-insert
|
|
|
|
|
?\s width (eat--t-face-face
|
|
|
|
|
(eat--t-term-face eat--t-term)))
|
|
|
|
|
(backward-char (- width moved))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-fix-partial-multi-col-char ()
|
|
|
|
|
"Replace any partial multi-column character with spaces."
|
|
|
|
|
(let ((face (eat--t-face-face
|
|
|
|
|
(eat--t-term-face eat--t-term))))
|
|
|
|
|
(if (get-text-property (point) 'eat--t-invisible-space)
|
|
|
|
|
(let ((start-pos (point))
|
|
|
|
|
(count nil))
|
2022-12-15 13:52:08 +06:00
|
|
|
|
(goto-char (or (next-single-property-change
|
|
|
|
|
(point) 'eat--t-invisible-space)
|
|
|
|
|
(point-max)))
|
2022-11-28 03:01:45 +06:00
|
|
|
|
(setq count (- (1+ (point)) start-pos))
|
|
|
|
|
;; Make sure we really overwrote the character
|
|
|
|
|
;; partially.
|
|
|
|
|
(when (< count (get-text-property
|
|
|
|
|
(point) 'eat--t-char-width))
|
|
|
|
|
(delete-region start-pos (1+ (point)))
|
|
|
|
|
(eat--t-repeated-insert ?\s count face))
|
|
|
|
|
(goto-char start-pos))
|
|
|
|
|
;; Detect the case where we have deleted all the invisible
|
|
|
|
|
;; spaces before, but not the multi-column character itself.
|
|
|
|
|
(when-let* (((not (eobp)))
|
|
|
|
|
(w (get-text-property (point) 'eat--t-char-width))
|
|
|
|
|
((> w 1)))
|
|
|
|
|
;; `delete-char' also works, but it does more checks, so
|
|
|
|
|
;; hopefully this will be faster.
|
|
|
|
|
(delete-region (point) (1+ (point)))
|
2022-12-22 20:27:50 +06:00
|
|
|
|
(insert (propertize " " 'face face 'font-lock-face face))
|
2022-11-28 03:01:45 +06:00
|
|
|
|
(backward-char)))))
|
|
|
|
|
|
2022-11-28 18:48:38 +06:00
|
|
|
|
(defconst eat--t-dec-line-drawing-chars
|
|
|
|
|
(eval-and-compile
|
|
|
|
|
(let ((alist '((?+ . ?→)
|
|
|
|
|
(?, . ?←)
|
|
|
|
|
(?- . ?↑)
|
|
|
|
|
(?. . ?↓)
|
|
|
|
|
(?0 . ?█)
|
|
|
|
|
(?\` . ?<3F>)
|
|
|
|
|
(?a . ?▒)
|
|
|
|
|
(?b . ?␉)
|
|
|
|
|
(?c . ?␌)
|
|
|
|
|
(?d . ?␍)
|
|
|
|
|
(?e . ?␊)
|
|
|
|
|
(?f . ?°)
|
|
|
|
|
(?g . ?±)
|
|
|
|
|
(?h . ?░)
|
|
|
|
|
(?i . ?#)
|
|
|
|
|
(?j . ?┘)
|
|
|
|
|
(?k . ?┐)
|
|
|
|
|
(?l . ?┌)
|
|
|
|
|
(?m . ?└)
|
|
|
|
|
(?n . ?┼)
|
|
|
|
|
(?o . ?⎺)
|
|
|
|
|
(?p . ?⎻)
|
|
|
|
|
(?q . ?─)
|
|
|
|
|
(?r . ?⎼)
|
|
|
|
|
(?s . ?⎽)
|
|
|
|
|
(?t . ?├)
|
|
|
|
|
(?u . ?┤)
|
|
|
|
|
(?v . ?┴)
|
|
|
|
|
(?w . ?┬)
|
|
|
|
|
(?x . ?│)
|
|
|
|
|
(?y . ?≤)
|
|
|
|
|
(?z . ?≥)
|
|
|
|
|
(?{ . ?π)
|
|
|
|
|
(?| . ?≠)
|
|
|
|
|
(?} . ?£)
|
|
|
|
|
(?~ . ?•)))
|
|
|
|
|
(table (make-hash-table :purecopy t)))
|
|
|
|
|
(dolist (pair alist)
|
|
|
|
|
(puthash (car pair) (cdr pair) table))
|
|
|
|
|
table))
|
|
|
|
|
"Hash table for DEC Line Drawing charset.
|
|
|
|
|
|
|
|
|
|
The key is the output character from client, and value of the
|
|
|
|
|
character to actually show.")
|
|
|
|
|
|
2022-11-28 20:50:58 +06:00
|
|
|
|
(defun eat--t-write (str &optional beg end)
|
|
|
|
|
"Write STR from BEG to END on display."
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setq beg (or beg 0))
|
|
|
|
|
(setq end (or end (length str)))
|
2022-11-28 20:50:58 +06:00
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(cursor (eat--t-disp-cursor disp))
|
|
|
|
|
(scroll-end (eat--t-term-scroll-end eat--t-term))
|
|
|
|
|
(charset
|
|
|
|
|
(alist-get (car (eat--t-term-charset eat--t-term))
|
|
|
|
|
(cdr (eat--t-term-charset eat--t-term))))
|
|
|
|
|
(face (eat--t-face-face (eat--t-term-face eat--t-term)))
|
|
|
|
|
;; Alist of indices and width of multi-column characters.
|
|
|
|
|
(multi-col-char-indices nil)
|
|
|
|
|
(inserted-till beg))
|
|
|
|
|
(cl-assert charset)
|
2022-11-28 19:37:17 +06:00
|
|
|
|
;; Find all the multi-column wide characters in ST; hopefully it
|
|
|
|
|
;; won't slow down showing plain ASCII.
|
|
|
|
|
(setq multi-col-char-indices
|
2022-11-28 20:50:58 +06:00
|
|
|
|
(cl-loop for i from beg to (1- end)
|
2022-11-28 19:37:17 +06:00
|
|
|
|
when (/= (char-width (aref str i)) 1)
|
|
|
|
|
collect (cons i (char-width (aref str i)))))
|
2022-11-28 20:50:58 +06:00
|
|
|
|
;; If the position isn't safe, replace the multi-column
|
|
|
|
|
;; character with spaces to make it safe.
|
|
|
|
|
(eat--t-make-pos-safe)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; TODO: Comment.
|
|
|
|
|
;; REVIEW: This probably needs to be updated.
|
2022-11-28 20:50:58 +06:00
|
|
|
|
(while (< inserted-till end)
|
|
|
|
|
;; Insert STR, and record the width of STR inserted
|
|
|
|
|
;; successfully.
|
|
|
|
|
(let ((ins-count
|
|
|
|
|
(named-let write
|
|
|
|
|
((max (min (- (eat--t-disp-width disp)
|
|
|
|
|
(1- (eat--t-cur-x cursor)))
|
|
|
|
|
(+ (- end inserted-till)
|
|
|
|
|
(cl-loop
|
|
|
|
|
for p in multi-col-char-indices
|
|
|
|
|
sum (1- (cdr p))))))
|
|
|
|
|
(written 0))
|
|
|
|
|
(let* ((next-multi-col (car multi-col-char-indices))
|
|
|
|
|
(end (+ inserted-till max))
|
|
|
|
|
(e (if next-multi-col
|
|
|
|
|
;; Exclude the multi-column character.
|
|
|
|
|
(min (car next-multi-col) end)
|
|
|
|
|
end))
|
|
|
|
|
(wrote (- e inserted-till)))
|
|
|
|
|
(cl-assert (>= wrote 0))
|
|
|
|
|
(let ((s (substring str inserted-till e)))
|
|
|
|
|
;; Convert STR to Unicode according to the
|
|
|
|
|
;; current character set.
|
|
|
|
|
(pcase-exhaustive charset
|
|
|
|
|
;; For `us-ascii', the default, no conversion
|
|
|
|
|
;; is necessary.
|
|
|
|
|
('us-ascii)
|
|
|
|
|
;; `dec-line-drawing' contains various
|
|
|
|
|
;; characters useful for drawing line diagram,
|
|
|
|
|
;; so it is a must. This is also possible
|
|
|
|
|
;; with `us-ascii', thanks to Unicode, but the
|
|
|
|
|
;; character set `dec-line-drawing' is usually
|
|
|
|
|
;; less expensive in terms of bytes needed to
|
|
|
|
|
;; transfer than `us-ascii'.
|
|
|
|
|
('dec-line-drawing
|
|
|
|
|
(dotimes (i (length s))
|
|
|
|
|
(when-let*
|
|
|
|
|
((r (gethash
|
|
|
|
|
(aref s i)
|
|
|
|
|
eat--t-dec-line-drawing-chars)))
|
|
|
|
|
(aset s i r)))))
|
|
|
|
|
;; Add face.
|
|
|
|
|
(put-text-property 0 (length s) 'face face s)
|
2022-12-22 20:27:50 +06:00
|
|
|
|
(put-text-property
|
|
|
|
|
0 (length s) 'font-lock-face face s)
|
2022-11-28 20:50:58 +06:00
|
|
|
|
(insert s))
|
|
|
|
|
(setq inserted-till e)
|
|
|
|
|
(if (or (null next-multi-col)
|
|
|
|
|
(< (- end e) (cdr next-multi-col)))
|
|
|
|
|
;; Either everything is done, or we reached
|
|
|
|
|
;; the limit.
|
|
|
|
|
(+ written wrote)
|
|
|
|
|
;; There are many characters which are too
|
|
|
|
|
;; narrow for `char-width' to return 1. XTerm,
|
|
|
|
|
;; Kitty and St seems to ignore them, so we too.
|
|
|
|
|
(if (zerop (cdr next-multi-col))
|
|
|
|
|
(cl-incf inserted-till)
|
|
|
|
|
(insert
|
|
|
|
|
;; Make sure the multi-column character
|
|
|
|
|
;; occupies the same number of characters as
|
|
|
|
|
;; its width.
|
|
|
|
|
(propertize
|
|
|
|
|
(make-string (1- (cdr next-multi-col)) ?\s)
|
2022-12-22 20:27:50 +06:00
|
|
|
|
'invisible t 'face face 'font-lock-face face
|
2022-11-28 20:50:58 +06:00
|
|
|
|
'eat--t-invisible-space t
|
|
|
|
|
'eat--t-char-width (cdr next-multi-col))
|
|
|
|
|
;; Now insert the multi-column character.
|
|
|
|
|
(propertize
|
|
|
|
|
(substring str inserted-till
|
|
|
|
|
(cl-incf inserted-till))
|
2022-12-22 20:27:50 +06:00
|
|
|
|
'face face 'font-lock-face face
|
2022-11-28 20:50:58 +06:00
|
|
|
|
'eat--t-char-width (cdr next-multi-col))))
|
|
|
|
|
(setf multi-col-char-indices
|
|
|
|
|
(cdr multi-col-char-indices))
|
|
|
|
|
(write (- max wrote (cdr next-multi-col))
|
|
|
|
|
(+ written wrote
|
|
|
|
|
(cdr next-multi-col))))))))
|
|
|
|
|
(cl-incf (eat--t-cur-x cursor) ins-count)
|
|
|
|
|
(if (eat--t-term-ins-mode eat--t-term)
|
|
|
|
|
(delete-region
|
|
|
|
|
(save-excursion
|
|
|
|
|
(eat--t-col-motion (- (eat--t-disp-width disp)
|
|
|
|
|
(1- (eat--t-cur-x cursor))))
|
|
|
|
|
;; Make sure the point is safe.
|
|
|
|
|
(eat--t-move-before-to-safe)
|
|
|
|
|
(point))
|
|
|
|
|
(car (eat--t-eol)))
|
|
|
|
|
(delete-region (point) (min (+ ins-count (point))
|
|
|
|
|
(car (eat--t-eol))))
|
|
|
|
|
;; Replace any partially-overwritten character with
|
|
|
|
|
;; spaces.
|
|
|
|
|
(eat--t-fix-partial-multi-col-char))
|
|
|
|
|
(when (> (eat--t-cur-x cursor) (eat--t-disp-width disp))
|
|
|
|
|
(if (not (eat--t-term-auto-margin eat--t-term))
|
|
|
|
|
(eat--t-cur-left 1)
|
|
|
|
|
(when (< inserted-till end)
|
|
|
|
|
(when (= (eat--t-cur-y cursor) scroll-end)
|
|
|
|
|
(eat--t-scroll-up 1 'as-side-effect))
|
|
|
|
|
(if (= (eat--t-cur-y cursor) scroll-end)
|
|
|
|
|
(eat--t-carriage-return)
|
|
|
|
|
(if (= (point) (point-max))
|
|
|
|
|
(insert #("\n" 0 1 (eat--t-wrap-line t)))
|
|
|
|
|
(put-text-property (point) (1+ (point))
|
|
|
|
|
'eat--t-wrap-line t)
|
|
|
|
|
(forward-char))
|
|
|
|
|
(1value (setf (eat--t-cur-x cursor) 1))
|
|
|
|
|
(cl-incf (eat--t-cur-y cursor))))))))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-horizontal-tab (&optional n)
|
|
|
|
|
"Go to the Nth next tabulation stop.
|
|
|
|
|
|
|
|
|
|
N default to 1."
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
;; N must be positive.
|
|
|
|
|
(setq n (max (or n 1) 1))
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
;; Do some math calculate the distance of the Nth next tabulation
|
|
|
|
|
;; stop from cursor, and go there.
|
|
|
|
|
(eat--t-cur-right (+ (- 8 (mod (1- (eat--t-cur-x cursor)) 8))
|
|
|
|
|
(* (1- n) 8)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-horizontal-backtab (&optional n)
|
|
|
|
|
"Go to the Nth previous tabulation stop.
|
|
|
|
|
|
|
|
|
|
N default to 1."
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
;; N must be positive.
|
|
|
|
|
(setq n (max (or n 1) 1))
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
;; Do some math calculate the distance of the Nth next tabulation
|
|
|
|
|
;; stop from cursor, and go there.
|
|
|
|
|
(eat--t-cur-left (+ (1+ (mod (- (eat--t-cur-x cursor) 2) 8))
|
|
|
|
|
(* (1- n) 8)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-index ()
|
|
|
|
|
"Go to the next line preserving column, scrolling if necessary."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(cursor (eat--t-disp-cursor disp))
|
|
|
|
|
(scroll-end (eat--t-term-scroll-end eat--t-term))
|
|
|
|
|
;; Are we inside scroll region?
|
|
|
|
|
(in-scroll-region (<= (eat--t-cur-y cursor) scroll-end)))
|
|
|
|
|
;; If this is the last line (of the scroll region or the display),
|
|
|
|
|
;; scroll up, otherwise move cursor downward.
|
|
|
|
|
(if (= (if in-scroll-region scroll-end (eat--t-disp-height disp))
|
|
|
|
|
(eat--t-cur-y cursor))
|
|
|
|
|
(eat--t-scroll-up 1)
|
|
|
|
|
(eat--t-cur-down 1))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-carriage-return ()
|
|
|
|
|
"Go to column one."
|
|
|
|
|
(eat--t-cur-horizontal-abs 1))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-line-feed ()
|
|
|
|
|
"Go to the first column of the next line, scrolling if necessary."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(cursor (eat--t-disp-cursor disp))
|
|
|
|
|
(scroll-end (eat--t-term-scroll-end eat--t-term))
|
|
|
|
|
;; Are we inside scroll region?
|
|
|
|
|
(in-scroll-region (<= (eat--t-cur-y cursor) scroll-end)))
|
|
|
|
|
;; If we are at the very end of the terminal, we might have some
|
|
|
|
|
;; optimizations.
|
|
|
|
|
(if (= (point) (point-max))
|
|
|
|
|
;; If the cursor is above the last line of the scroll region
|
|
|
|
|
;; (or the display, if we are outside the scroll region), we
|
|
|
|
|
;; can simply insert a newline and update the cursor position.
|
|
|
|
|
(if (/= (if in-scroll-region
|
|
|
|
|
scroll-end
|
|
|
|
|
(eat--t-disp-height disp))
|
|
|
|
|
(eat--t-cur-y cursor))
|
|
|
|
|
(progn
|
|
|
|
|
(insert ?\n)
|
|
|
|
|
(setf (eat--t-cur-x cursor) 1)
|
|
|
|
|
(cl-incf (eat--t-cur-y cursor)))
|
|
|
|
|
;; This is the last line. We need to scroll up.
|
|
|
|
|
(eat--t-scroll-up 1 'as-side-effect)
|
|
|
|
|
;; If we're still at the last line (only happens when the
|
|
|
|
|
;; display has only a single line), go to column one of it.
|
|
|
|
|
(if (= (if in-scroll-region
|
|
|
|
|
scroll-end
|
|
|
|
|
(eat--t-disp-height disp))
|
|
|
|
|
(eat--t-cur-y cursor))
|
|
|
|
|
(eat--t-carriage-return)
|
|
|
|
|
;; If we are somehow moved from the end of terminal,
|
|
|
|
|
;; `eat--t-beg-of-next-line' is the best option.
|
|
|
|
|
(if (/= (point) (point-max))
|
|
|
|
|
(eat--t-beg-of-next-line 1)
|
|
|
|
|
;; We are still at the end! We can can simply insert a
|
|
|
|
|
;; newline and update the cursor position.
|
|
|
|
|
(insert ?\n)
|
|
|
|
|
(setf (eat--t-cur-x cursor) 1)
|
|
|
|
|
(cl-incf (eat--t-cur-y cursor)))))
|
|
|
|
|
;; We are not at the end of terminal. But we still have a last
|
|
|
|
|
;; chance. `eat--t-beg-of-next-line' is usually faster than
|
|
|
|
|
;; `eat--t-carriage-return' followed by `eat--t-index', so if
|
|
|
|
|
;; there is at least a single line (in the scroll region, if the
|
|
|
|
|
;; cursor in the scroll region, otherwise in the display)
|
|
|
|
|
;; underneath the cursor, we can use `eat--t-beg-of-next-line'.
|
|
|
|
|
(if (/= (if in-scroll-region
|
|
|
|
|
scroll-end
|
|
|
|
|
(eat--t-disp-height disp))
|
|
|
|
|
(eat--t-cur-y cursor))
|
|
|
|
|
(eat--t-beg-of-next-line 1)
|
|
|
|
|
;; We don't have any other option, so we must use the most
|
|
|
|
|
;; time-expensive option.
|
|
|
|
|
(eat--t-carriage-return)
|
|
|
|
|
(eat--t-index)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-reverse-index ()
|
|
|
|
|
"Go to the previous line preserving column, scrolling if needed."
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let* ((cursor (eat--t-disp-cursor
|
|
|
|
|
(eat--t-term-display eat--t-term)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(scroll-begin (eat--t-term-scroll-begin eat--t-term))
|
|
|
|
|
;; Are we in the scroll region?
|
|
|
|
|
(in-scroll-region (<= scroll-begin (eat--t-cur-y cursor))))
|
|
|
|
|
;; If this is the first line (of the scroll region or the
|
|
|
|
|
;; display), scroll down, otherwise move cursor upward.
|
|
|
|
|
(if (= (if in-scroll-region scroll-begin 1)
|
|
|
|
|
(eat--t-cur-y cursor))
|
|
|
|
|
(eat--t-scroll-down 1)
|
|
|
|
|
(eat--t-cur-up 1))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-bell ()
|
|
|
|
|
"Ring the bell."
|
|
|
|
|
;; Call the UI's bell handler.
|
|
|
|
|
(funcall (eat--t-term-bell-fn eat--t-term) eat--t-term))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-form-feed ()
|
|
|
|
|
"Insert a vertical tab."
|
|
|
|
|
;; Form feed is same as `eat--t-index'.
|
|
|
|
|
(eat--t-index))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-save-cur ()
|
|
|
|
|
"Save current cursor position."
|
|
|
|
|
(let ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(saved-face (eat--t-copy-face
|
|
|
|
|
(eat--t-term-face eat--t-term))))
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
;; Save cursor position.
|
|
|
|
|
(setf (eat--t-disp-saved-cursor disp)
|
|
|
|
|
(eat--t-copy-cur (eat--t-disp-cursor disp)))
|
|
|
|
|
;; Save SGR attributes.
|
|
|
|
|
(setf (eat--t-term-saved-face eat--t-term) saved-face)
|
|
|
|
|
;; We use side-effects, so make sure the saved face doesn't share
|
|
|
|
|
;; structure with the current face.
|
|
|
|
|
(setf (eat--t-face-face saved-face)
|
|
|
|
|
(copy-tree (eat--t-face-face saved-face)))
|
|
|
|
|
(setf (eat--t-face-underline-color saved-face)
|
|
|
|
|
(copy-tree (eat--t-face-underline-color saved-face)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-restore-cur ()
|
|
|
|
|
"Restore previously save cursor position."
|
|
|
|
|
(let ((saved (eat--t-disp-saved-cursor
|
|
|
|
|
(eat--t-term-display eat--t-term))))
|
|
|
|
|
;; Restore cursor position.
|
|
|
|
|
(eat--t-goto (eat--t-cur-y saved) (eat--t-cur-x saved))
|
|
|
|
|
;; Restore SGR attributes.
|
|
|
|
|
(setf (eat--t-term-face eat--t-term)
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(copy-tree (eat--t-term-saved-face eat--t-term)))
|
|
|
|
|
(setf (eat--t-face-underline-color (eat--t-term-face eat--t-term))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(copy-tree (eat--t-face-underline-color
|
|
|
|
|
(eat--t-term-face eat--t-term))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-erase-in-line (&optional n)
|
|
|
|
|
"Erase part of current line, but don't move cursor.
|
|
|
|
|
|
|
|
|
|
N defaults to 0. When N is 0, erase cursor to end of line. When N is
|
|
|
|
|
1, erase beginning of line to cursor. When N is 2, erase whole line."
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let ((face (eat--t-term-face eat--t-term)))
|
2022-11-28 22:29:15 +06:00
|
|
|
|
(pcase-exhaustive n
|
2022-09-02 20:03:33 +06:00
|
|
|
|
((or 0 'nil (pred (< 2)))
|
|
|
|
|
;; Delete cursor position (inclusive) to end of line.
|
|
|
|
|
(delete-region (point) (car (eat--t-eol)))
|
|
|
|
|
;; If the SGR background attribute is set, we need to fill the
|
|
|
|
|
;; erased area with that background.
|
|
|
|
|
(when (eat--t-face-bg face)
|
|
|
|
|
(save-excursion
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
(eat--t-repeated-insert
|
|
|
|
|
?\s (1+ (- (eat--t-disp-width disp)
|
|
|
|
|
(eat--t-cur-x cursor)))
|
|
|
|
|
(and (eat--t-face-bg face)
|
|
|
|
|
(eat--t-face-face face)))))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(1
|
|
|
|
|
;; Delete beginning of line to cursor position (inclusive).
|
|
|
|
|
(delete-region (car (eat--t-bol))
|
|
|
|
|
(if (or (= (point) (point-max))
|
|
|
|
|
(= (char-after) ?\n))
|
|
|
|
|
(point)
|
|
|
|
|
(1+ (point))))
|
|
|
|
|
;; Fill the region with spaces, use SGR background attribute
|
|
|
|
|
;; if set.
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let ((cursor (eat--t-disp-cursor
|
|
|
|
|
(eat--t-term-display eat--t-term))))
|
|
|
|
|
(eat--t-repeated-insert ?\s (eat--t-cur-x cursor)
|
|
|
|
|
(and (eat--t-face-bg face)
|
|
|
|
|
(eat--t-face-face face))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; We erased the character at the cursor position, so after
|
|
|
|
|
;; fill with spaces we are still off by one column; so move a
|
|
|
|
|
;; column backward.
|
|
|
|
|
(backward-char))
|
|
|
|
|
(2
|
|
|
|
|
;; Delete whole line.
|
|
|
|
|
(delete-region (car (eat--t-bol)) (car (eat--t-eol)))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
;; Fill the region before cursor position with spaces, use
|
|
|
|
|
;; SGR background attribute if set.
|
|
|
|
|
(eat--t-repeated-insert ?\s (1- (eat--t-cur-x cursor))
|
|
|
|
|
(and (eat--t-face-bg face)
|
|
|
|
|
(eat--t-face-face face)))
|
|
|
|
|
;; If the SGR background attribute is set, we need to fill
|
|
|
|
|
;; the erased area including and after cursor position with
|
|
|
|
|
;; that background.
|
|
|
|
|
(when (eat--t-face-bg face)
|
|
|
|
|
(save-excursion
|
|
|
|
|
(eat--t-repeated-insert
|
|
|
|
|
?\s (1+ (- (eat--t-disp-width disp)
|
|
|
|
|
(eat--t-cur-x cursor)))
|
|
|
|
|
(and (eat--t-face-bg face)
|
|
|
|
|
(eat--t-face-face face))))))))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-erase-in-disp (&optional n)
|
|
|
|
|
"Erase part of display.
|
|
|
|
|
|
|
|
|
|
N defaults to 0. When N is 0, erase cursor to end of display. When N
|
|
|
|
|
is 1, erase beginning of display to cursor. In both on the previous
|
|
|
|
|
cases, don't move cursor. When N is 2, erase display and reset cursor
|
|
|
|
|
to (1, 1). When N is 3, also erase the scrollback."
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let ((face (eat--t-term-face eat--t-term)))
|
2022-11-28 22:29:15 +06:00
|
|
|
|
(pcase-exhaustive n
|
2022-09-02 20:03:33 +06:00
|
|
|
|
((or 0 'nil (pred (< 3)))
|
|
|
|
|
;; Delete from cursor position (inclusive) to end of terminal.
|
|
|
|
|
(delete-region (point) (point-max))
|
|
|
|
|
;; If the SGR background attribute is set, we need to fill the
|
|
|
|
|
;; erased area with that background.
|
|
|
|
|
(when (eat--t-face-bg face)
|
|
|
|
|
;; `save-excursion' probably uses marker to save point, which
|
|
|
|
|
;; doesn't work in this case. So we the store the point as a
|
|
|
|
|
;; integer.
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let* ((pos (point))
|
|
|
|
|
(disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Fill current line.
|
2022-11-27 00:21:56 +06:00
|
|
|
|
(eat--t-repeated-insert ?\s (1+ (- (eat--t-disp-width disp)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat--t-cur-x cursor)))
|
|
|
|
|
(eat--t-face-face face))
|
|
|
|
|
;; Fill the following lines.
|
|
|
|
|
(dotimes (_ (- (eat--t-disp-height disp)
|
|
|
|
|
(eat--t-cur-y cursor)))
|
|
|
|
|
(insert ?\n)
|
2022-11-27 00:21:56 +06:00
|
|
|
|
(eat--t-repeated-insert ?\s (eat--t-disp-width disp)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat--t-face-face face)))
|
|
|
|
|
;; Restore position.
|
|
|
|
|
(goto-char pos))))
|
|
|
|
|
(1
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(cursor (eat--t-disp-cursor disp))
|
|
|
|
|
(y (eat--t-cur-y cursor))
|
|
|
|
|
(x (eat--t-cur-x cursor))
|
|
|
|
|
;; Should we erase including the cursor position?
|
|
|
|
|
(incl-point (/= (point) (point-max))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Delete the region to be erased.
|
|
|
|
|
(delete-region (eat--t-disp-begin disp)
|
|
|
|
|
(if incl-point (1+ (point)) (point)))
|
|
|
|
|
;; If the SGR background attribute isn't set, insert
|
|
|
|
|
;; newlines, otherwise fill the erased area above the current
|
|
|
|
|
;; line with background color.
|
|
|
|
|
(if (not (eat--t-face-bg face))
|
|
|
|
|
(eat--t-repeated-insert ?\n (1- y))
|
|
|
|
|
(dotimes (_ (1- y))
|
2022-11-27 00:21:56 +06:00
|
|
|
|
(eat--t-repeated-insert ?\s (eat--t-disp-width disp)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat--t-face-face face))
|
|
|
|
|
(insert ?\n)))
|
|
|
|
|
;; Fill the current line to keep the cursor unmoved. Use
|
|
|
|
|
;; background if the corresponding SGR attribute is set.
|
2022-11-27 00:21:56 +06:00
|
|
|
|
(eat--t-repeated-insert ?\s x (and (eat--t-face-bg face)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat--t-face-face face)))
|
|
|
|
|
;; We are off by one column; so move a column backward.
|
|
|
|
|
(when incl-point
|
|
|
|
|
(backward-char))))
|
|
|
|
|
((or 2 3)
|
|
|
|
|
;; Move to the display beginning.
|
|
|
|
|
(eat--t-goto 1 1)
|
|
|
|
|
;; Delete everything in the display, and if N is 3, also delete
|
|
|
|
|
;; everything in the scrollback area.
|
|
|
|
|
(delete-region (if (= n 2) (point) (point-min))
|
|
|
|
|
(point-max))
|
|
|
|
|
;; If the SGR background attribute is set, fill the display
|
|
|
|
|
;; with that background.
|
|
|
|
|
(when (eat--t-face-bg face)
|
|
|
|
|
;; `save-excursion' probably uses marker to save point, which
|
|
|
|
|
;; doesn't work in this case. So we the store the point as a
|
|
|
|
|
;; integer.
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let ((pos (point))
|
|
|
|
|
(disp (eat--t-term-display eat--t-term)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(dotimes (i (eat--t-disp-height disp))
|
|
|
|
|
(unless (zerop i)
|
|
|
|
|
(insert ?\n))
|
2022-11-27 00:21:56 +06:00
|
|
|
|
(eat--t-repeated-insert ?\s (eat--t-disp-width disp)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat--t-face-face face)))
|
|
|
|
|
;; Restore point.
|
|
|
|
|
(goto-char pos)))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-device-status-report ()
|
|
|
|
|
"Send the current Y and X coordinate to client."
|
|
|
|
|
;; TODO: Is this really device status report function?
|
|
|
|
|
(let ((cursor (eat--t-disp-cursor
|
|
|
|
|
(eat--t-term-display eat--t-term))))
|
|
|
|
|
(funcall (eat--t-term-input-fn eat--t-term) eat--t-term
|
|
|
|
|
(format "\e[%i;%iR" (eat--t-cur-y cursor)
|
|
|
|
|
(eat--t-cur-x cursor)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-set-cursor-state (state)
|
|
|
|
|
"Set cursor state to STATE.
|
|
|
|
|
|
|
|
|
|
STATE one of the `:default', `:invisible', `:very-visible'."
|
|
|
|
|
(unless (eq (eat--t-term-cur-state eat--t-term) state)
|
|
|
|
|
;; Update state.
|
|
|
|
|
(setf (eat--t-term-cur-state eat--t-term) state)
|
|
|
|
|
;; Inform the UI.
|
|
|
|
|
(funcall (eat--t-term-set-cursor-fn eat--t-term) eat--t-term
|
|
|
|
|
state)))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-default-cursor ()
|
|
|
|
|
"Set the cursor to its default state."
|
|
|
|
|
(eat--t-set-cursor-state
|
|
|
|
|
(if (eat--t-term-cur-blinking-p eat--t-term)
|
|
|
|
|
:very-visible
|
|
|
|
|
:default)))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-invisible-cursor ()
|
|
|
|
|
"Make the cursor invisible."
|
|
|
|
|
(eat--t-set-cursor-state :invisible))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-blinking-cursor ()
|
|
|
|
|
"Make the cursor blink."
|
|
|
|
|
(setf (eat--t-term-cur-blinking-p eat--t-term) t)
|
|
|
|
|
(when (eq (eat--t-term-cur-state eat--t-term) :default)
|
|
|
|
|
(eat--t-set-cursor-state :very-visible)))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-non-blinking-cursor ()
|
|
|
|
|
"Make the cursor not blink."
|
|
|
|
|
(setf (eat--t-term-cur-blinking-p eat--t-term) nil)
|
|
|
|
|
(when (eq (eat--t-term-cur-state eat--t-term) :very-visible)
|
|
|
|
|
(eat--t-set-cursor-state :default)))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-enable-bracketed-yank ()
|
|
|
|
|
"Enable bracketed yank mode."
|
|
|
|
|
(setf (eat--t-term-bracketed-yank eat--t-term) t))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-disable-bracketed-yank ()
|
|
|
|
|
"Disable bracketed yank mode."
|
|
|
|
|
(setf (eat--t-term-bracketed-yank eat--t-term) nil))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-enable-alt-disp ()
|
|
|
|
|
"Enable alternative display."
|
|
|
|
|
;; Effective only when alternative display is enabled by user.
|
|
|
|
|
(when eat-enable-alternative-display
|
|
|
|
|
;; Make sure we not already in the alternative display.
|
|
|
|
|
(unless (eat--t-term-main-display eat--t-term)
|
|
|
|
|
;; Store the current display, including scrollback.
|
|
|
|
|
(let ((main-disp (eat--t-copy-disp
|
|
|
|
|
(eat--t-term-display eat--t-term))))
|
|
|
|
|
(setf (eat--t-disp-begin main-disp)
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(- (eat--t-disp-begin main-disp) (point-min)))
|
|
|
|
|
(setf (eat--t-disp-old-begin main-disp)
|
|
|
|
|
(- (eat--t-disp-old-begin main-disp) (point-min)))
|
|
|
|
|
(setf (eat--t-disp-cursor main-disp)
|
|
|
|
|
(eat--t-copy-cur (eat--t-disp-cursor main-disp)))
|
|
|
|
|
(setf (eat--t-disp-saved-cursor main-disp)
|
|
|
|
|
(eat--t-copy-cur (eat--t-disp-saved-cursor main-disp)))
|
|
|
|
|
(setf (eat--t-cur-position (eat--t-disp-cursor main-disp))
|
|
|
|
|
(- (point) (point-min)))
|
|
|
|
|
(setf (eat--t-term-main-display eat--t-term)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(cons main-disp (buffer-string)))
|
|
|
|
|
;; Delete everything, and move to the beginning of terminal.
|
|
|
|
|
(delete-region (point-min) (point-max))
|
|
|
|
|
(eat--t-goto 1 1)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-disable-alt-disp (&optional dont-move-cursor)
|
|
|
|
|
"Disable alternative display.
|
|
|
|
|
|
|
|
|
|
If DONT-MOVE-CURSOR is non-nil, don't move cursor from current
|
|
|
|
|
position."
|
|
|
|
|
;; Make sure we in the alternative display.
|
|
|
|
|
(when (eat--t-term-main-display eat--t-term)
|
2022-11-28 12:40:19 +06:00
|
|
|
|
(let ((main-disp (eat--t-term-main-display eat--t-term))
|
|
|
|
|
(old-y (eat--t-cur-y
|
|
|
|
|
(eat--t-disp-cursor
|
|
|
|
|
(eat--t-term-display eat--t-term))))
|
|
|
|
|
(old-x (eat--t-cur-x
|
|
|
|
|
(eat--t-disp-cursor
|
|
|
|
|
(eat--t-term-display eat--t-term))))
|
|
|
|
|
(width (eat--t-disp-width
|
|
|
|
|
(eat--t-term-display eat--t-term)))
|
|
|
|
|
(height (eat--t-disp-height
|
|
|
|
|
(eat--t-term-display eat--t-term))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Delete everything.
|
|
|
|
|
(delete-region (point-min) (point-max))
|
|
|
|
|
;; Restore the main display.
|
|
|
|
|
(insert (cdr main-disp))
|
|
|
|
|
(setf (eat--t-cur-position (eat--t-disp-cursor (car main-disp)))
|
|
|
|
|
(copy-marker (+ (point-min)
|
|
|
|
|
(eat--t-cur-position
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(eat--t-disp-cursor (car main-disp))))))
|
|
|
|
|
(setf (eat--t-disp-old-begin (car main-disp))
|
Combine multiple setq/setf/setq-local into one
* eat.el (eat--t-reset, eat--t-goto, eat--t-write)
(eat--t-save-cur, eat--t-enable-alt-disp)
(eat--t-change-scroll-region, eat--t-set-sgr-params)
(eat--t-manipulate-selection, eat--t-handle-output)
(eat--t-resize, eat--flip-slow-blink-state)
(eat--flip-fast-blink-state, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-local-mode)
(eat--eshell-exec-visual, eat--trace-exec)
(eat--eshell-trace-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Combine multiple setq/setf/setq-local into one wherever
possible.
2022-11-28 21:54:55 +06:00
|
|
|
|
(copy-marker (+ (point-min)
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(eat--t-disp-old-begin (car main-disp)))))
|
|
|
|
|
(setf (eat--t-disp-begin (car main-disp))
|
Combine multiple setq/setf/setq-local into one
* eat.el (eat--t-reset, eat--t-goto, eat--t-write)
(eat--t-save-cur, eat--t-enable-alt-disp)
(eat--t-change-scroll-region, eat--t-set-sgr-params)
(eat--t-manipulate-selection, eat--t-handle-output)
(eat--t-resize, eat--flip-slow-blink-state)
(eat--flip-fast-blink-state, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-local-mode)
(eat--eshell-exec-visual, eat--trace-exec)
(eat--eshell-trace-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Combine multiple setq/setf/setq-local into one wherever
possible.
2022-11-28 21:54:55 +06:00
|
|
|
|
(copy-marker (+ (point-min)
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(eat--t-disp-begin (car main-disp)))))
|
|
|
|
|
(setf (eat--t-term-display eat--t-term) (car main-disp)
|
Combine multiple setq/setf/setq-local into one
* eat.el (eat--t-reset, eat--t-goto, eat--t-write)
(eat--t-save-cur, eat--t-enable-alt-disp)
(eat--t-change-scroll-region, eat--t-set-sgr-params)
(eat--t-manipulate-selection, eat--t-handle-output)
(eat--t-resize, eat--flip-slow-blink-state)
(eat--flip-fast-blink-state, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-local-mode)
(eat--eshell-exec-visual, eat--trace-exec)
(eat--eshell-trace-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Combine multiple setq/setf/setq-local into one wherever
possible.
2022-11-28 21:54:55 +06:00
|
|
|
|
(eat--t-term-main-display eat--t-term) nil)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(goto-char (eat--t-cur-position
|
|
|
|
|
(eat--t-disp-cursor
|
|
|
|
|
(eat--t-term-display eat--t-term))))
|
|
|
|
|
;; Maybe the terminal was resized after enabling alternative
|
|
|
|
|
;; display, so we have to resize again.
|
|
|
|
|
(eat--t-resize width height)
|
|
|
|
|
;; Restore cursor position if DONT-MOVE-CURSOR is non-nil.
|
|
|
|
|
(when dont-move-cursor
|
|
|
|
|
(eat--t-goto old-y old-x)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-insert-char (n)
|
|
|
|
|
"Insert N empty (space) characters, preserving cursor."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
;; Make sure N is positive. If N is more than the number of
|
|
|
|
|
;; available columns available, set N to the maximum possible
|
|
|
|
|
;; value.
|
|
|
|
|
(setq n (min (- (eat--t-disp-width disp)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(1- (eat--t-cur-x cursor)))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(max (or n 1) 1)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Return if N is zero.
|
|
|
|
|
(unless (zerop n)
|
2022-11-28 03:01:45 +06:00
|
|
|
|
;; If the position isn't safe, replace the multi-column
|
|
|
|
|
;; character with spaces to make it safe.
|
|
|
|
|
(eat--t-make-pos-safe)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(save-excursion
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let ((face (eat--t-term-face eat--t-term)))
|
|
|
|
|
;; Insert N spaces, with SGR background if that attribute is
|
|
|
|
|
;; set.
|
|
|
|
|
(eat--t-repeated-insert
|
|
|
|
|
?\s n (and (eat--t-face-bg face) (eat--t-face-face face))))
|
|
|
|
|
;; Remove the characters that went beyond the edge of
|
|
|
|
|
;; display.
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat--t-col-motion (- (eat--t-disp-width disp)
|
|
|
|
|
(+ (1- (eat--t-cur-x cursor)) n)))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
;; Make sure we delete any multi-column character
|
|
|
|
|
;; completely.
|
2022-11-28 03:01:45 +06:00
|
|
|
|
(eat--t-move-before-to-safe)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(delete-region (point) (car (eat--t-eol)))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-delete-char (n)
|
|
|
|
|
"Delete N characters, preserving cursor."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(face (eat--t-term-face eat--t-term))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
;; Make sure N is positive. If N is more than the number of
|
|
|
|
|
;; available columns available, set N to the maximum possible
|
|
|
|
|
;; value.
|
|
|
|
|
(setq n (min (- (eat--t-disp-width disp)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(1- (eat--t-cur-x cursor)))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(max (or n 1) 1)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Return if N is zero.
|
|
|
|
|
(unless (zerop n)
|
2022-11-28 03:01:45 +06:00
|
|
|
|
;; If the position isn't safe, replace the multi-column
|
|
|
|
|
;; character with spaces to make it safe.
|
|
|
|
|
(eat--t-make-pos-safe)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(save-excursion
|
|
|
|
|
(let ((m (point)))
|
|
|
|
|
;; Delete N character on current line.
|
|
|
|
|
(eat--t-col-motion n)
|
|
|
|
|
(delete-region m (point))
|
2022-11-28 03:01:45 +06:00
|
|
|
|
;; Replace any partially-overwritten character with spaces.
|
|
|
|
|
(eat--t-fix-partial-multi-col-char)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; If SGR background attribute is set, fill N characters at
|
|
|
|
|
;; the right edge of display with that background.
|
|
|
|
|
(when (eat--t-face-bg face)
|
|
|
|
|
(save-excursion
|
|
|
|
|
(eat--t-goto-eol)
|
|
|
|
|
(let ((empty (1+ (- (eat--t-disp-width disp)
|
|
|
|
|
(eat--t-cur-x cursor)
|
|
|
|
|
(- (point) m)))))
|
|
|
|
|
;; Reach the position from where to start filling.
|
|
|
|
|
;; Use spaces if needed.
|
|
|
|
|
(when (> empty n)
|
2022-11-27 00:21:56 +06:00
|
|
|
|
(eat--t-repeated-insert ?\s (- empty n)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Fill with background.
|
|
|
|
|
(eat--t-repeated-insert
|
2022-11-27 00:21:56 +06:00
|
|
|
|
?\s (min empty n) (eat--t-face-face face))))))))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-erase-char (n)
|
|
|
|
|
"Make next N character cells empty, preserving cursor."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(face (eat--t-term-face eat--t-term))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
;; Make sure N is positive. If N is more than the number of
|
|
|
|
|
;; available columns available, set N to the maximum possible
|
|
|
|
|
;; value.
|
|
|
|
|
(setq n (min (- (eat--t-disp-width disp)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(1- (eat--t-cur-x cursor)))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(max (or n 1) 1)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Return if N is zero.
|
|
|
|
|
(unless (zerop n)
|
2022-11-28 03:01:45 +06:00
|
|
|
|
;; If the position isn't safe, replace the multi-column
|
|
|
|
|
;; character with spaces to make it safe.
|
|
|
|
|
(eat--t-make-pos-safe)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(save-excursion
|
|
|
|
|
(let ((m (point)))
|
|
|
|
|
;; Delete N character on current line.
|
|
|
|
|
(eat--t-col-motion n)
|
|
|
|
|
(delete-region m (point))
|
2022-11-28 03:01:45 +06:00
|
|
|
|
;; Replace any partially-overwritten character with spaces.
|
|
|
|
|
(eat--t-fix-partial-multi-col-char)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Insert N spaces, with background if SGR background
|
|
|
|
|
;; attribute is set.
|
|
|
|
|
(eat--t-repeated-insert
|
2022-11-27 00:21:56 +06:00
|
|
|
|
?\s n (and (eat--t-face-bg face)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat--t-face-face face))))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-insert-line (n)
|
|
|
|
|
"Insert N empty lines, preserving cursor."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(cursor (eat--t-disp-cursor disp))
|
|
|
|
|
(scroll-begin (eat--t-term-scroll-begin eat--t-term))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(scroll-end (eat--t-term-scroll-end eat--t-term)))
|
|
|
|
|
;; N should be positive and shouldn't exceed the number of lines
|
|
|
|
|
;; below cursor position and inside current scroll region.
|
|
|
|
|
(setq n (min (- (1+ (- scroll-end scroll-begin))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(1- (eat--t-cur-y cursor)))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(max (or n 1) 1)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Make sure we are in the scroll region and N is positive, return
|
|
|
|
|
;; on failure.
|
|
|
|
|
(when (and (<= scroll-begin (eat--t-cur-y cursor) scroll-end)
|
|
|
|
|
(not (zerop n)))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
;; This function doesn't move the cursor, but pushes all the
|
|
|
|
|
;; line below and including current line. So to keep the cursor
|
|
|
|
|
;; unmoved, go to the beginning of line and insert enough spaces
|
|
|
|
|
;; to not move the cursor.
|
|
|
|
|
(eat--t-goto-bol)
|
|
|
|
|
(let ((face (eat--t-term-face eat--t-term)))
|
|
|
|
|
(eat--t-repeated-insert ?\s (1- (eat--t-cur-x cursor))
|
|
|
|
|
(and (eat--t-face-bg face)
|
|
|
|
|
(eat--t-face-face face)))
|
|
|
|
|
(goto-char
|
|
|
|
|
(prog1 (point)
|
|
|
|
|
;; Insert N lines.
|
|
|
|
|
(if (not (eat--t-face-bg face))
|
|
|
|
|
(eat--t-repeated-insert ?\n n)
|
|
|
|
|
;; SGR background attribute set, so fill the inserted
|
|
|
|
|
;; lines with background.
|
|
|
|
|
(dotimes (i n)
|
|
|
|
|
;; Fill a line.
|
|
|
|
|
(eat--t-repeated-insert
|
|
|
|
|
?\s (if (not (zerop i))
|
|
|
|
|
(eat--t-disp-width disp)
|
|
|
|
|
;; The first inserted line is already filled
|
|
|
|
|
;; partially, so calculate the number columns
|
|
|
|
|
;; left to fill.
|
|
|
|
|
(1+ (- (eat--t-disp-width disp)
|
|
|
|
|
(eat--t-cur-x cursor))))
|
|
|
|
|
(eat--t-face-face face))
|
|
|
|
|
;; New line.
|
|
|
|
|
(insert ?\n)))
|
|
|
|
|
;; Delete the lines that were just pushed beyond the end of
|
|
|
|
|
;; scroll region.
|
|
|
|
|
(eat--t-goto-eol (- (1+ (- scroll-end scroll-begin))
|
|
|
|
|
(+ (- (eat--t-cur-y cursor)
|
|
|
|
|
(1- scroll-begin))
|
|
|
|
|
n)))
|
|
|
|
|
(delete-region (point) (car (eat--t-eol n)))))))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-delete-line (n)
|
|
|
|
|
"Delete N lines, preserving cursor."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(cursor (eat--t-disp-cursor disp))
|
|
|
|
|
(x (eat--t-cur-x cursor))
|
|
|
|
|
(scroll-begin (eat--t-term-scroll-begin eat--t-term))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(scroll-end (eat--t-term-scroll-end eat--t-term)))
|
|
|
|
|
;; N should be positive and shouldn't exceed the number of
|
|
|
|
|
;; lines below cursor position and inside current scroll
|
|
|
|
|
;; region.
|
|
|
|
|
(setq n (min (- (1+ (- scroll-end scroll-begin))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(1- (eat--t-cur-y cursor)))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(max (or n 1) 1)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Make sure we are in the scroll region and N is positive, return
|
|
|
|
|
;; on failure.
|
|
|
|
|
(when (and (<= scroll-begin (eat--t-cur-y cursor) scroll-end)
|
|
|
|
|
(not (zerop n)))
|
|
|
|
|
;; Delete N lines (including the current one).
|
|
|
|
|
(eat--t-goto-bol)
|
|
|
|
|
(save-excursion
|
|
|
|
|
(let ((m (point)))
|
|
|
|
|
(eat--t-goto-bol n)
|
|
|
|
|
(delete-region m (point))))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let ((face (eat--t-term-face eat--t-term)))
|
|
|
|
|
;; Keep the lines beyond end of scroll region unmoved.
|
|
|
|
|
(when (or (< scroll-end (eat--t-disp-height disp))
|
|
|
|
|
(eat--t-face-bg face))
|
|
|
|
|
(let* ((pos (point))
|
|
|
|
|
(move (- (1+ (- scroll-end scroll-begin))
|
|
|
|
|
(- (+ (eat--t-cur-y cursor) n)
|
|
|
|
|
(1- scroll-begin))))
|
|
|
|
|
(moved (eat--t-goto-eol move)))
|
|
|
|
|
(when (or (/= (point) (point-max))
|
|
|
|
|
(eat--t-face-bg face))
|
|
|
|
|
;; Move to the end of scroll region.
|
|
|
|
|
(eat--t-repeated-insert ?\n (- move moved))
|
|
|
|
|
;; Insert enough new lines, fill them when SGR
|
|
|
|
|
;; background attribute is set.
|
|
|
|
|
(if (not (eat--t-face-bg face))
|
|
|
|
|
(eat--t-repeated-insert ?\n n)
|
|
|
|
|
(dotimes (_ n)
|
|
|
|
|
(insert ?\n)
|
|
|
|
|
(eat--t-repeated-insert ?\s (eat--t-disp-width disp)
|
|
|
|
|
(eat--t-face-face face)))))
|
|
|
|
|
(goto-char pos))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Go to column where cursor is to preserve cursor position, use
|
|
|
|
|
;; spaces if needed to reach the position.
|
|
|
|
|
(eat--t-repeated-insert
|
2022-11-27 00:21:56 +06:00
|
|
|
|
?\s (- (1- x) (eat--t-col-motion (1- x)))))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-repeat-last-char (&optional n)
|
|
|
|
|
"Repeat last character N times."
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
;; N must be at least one.
|
|
|
|
|
(setq n (max (or n 1) 1))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(char
|
|
|
|
|
;; Get the character before cursor.
|
|
|
|
|
(when (< (eat--t-disp-begin disp) (point))
|
|
|
|
|
(if (get-text-property (1- (point)) 'eat--t-wrap-line)
|
|
|
|
|
;; The character before cursor is a newline to break
|
|
|
|
|
;; a long line, so use the character before that.
|
|
|
|
|
(when (< (eat--t-disp-begin disp) (1- (point)))
|
|
|
|
|
(char-before (1- (point))))
|
|
|
|
|
(char-before)))))
|
|
|
|
|
;; Insert `char' N times. Make sure `char' is a non-nil and not
|
|
|
|
|
;; a newline.
|
|
|
|
|
(when (and char (/= char ?\n))
|
|
|
|
|
(eat--t-write (make-string n char)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-change-scroll-region (&optional top bottom)
|
|
|
|
|
"Change the scroll region from lines TOP to BOTTOM (inclusive).
|
|
|
|
|
|
|
|
|
|
TOP defaults to 1 and BOTTOM defaults to the height of the display."
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(let ((disp (eat--t-term-display eat--t-term)))
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setq top (or top 1))
|
|
|
|
|
(setq bottom (or bottom (eat--t-disp-height disp)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; According to DEC's documentation (found somewhere on the
|
|
|
|
|
;; internet, but can't remember where), TOP and BOTTOM must be
|
|
|
|
|
;; within display, and BOTTOM must be below TOP. Otherwise the
|
|
|
|
|
;; control function is a nop.
|
|
|
|
|
(when (< 0 top bottom (1+ (eat--t-disp-height disp)))
|
Combine multiple setq/setf/setq-local into one
* eat.el (eat--t-reset, eat--t-goto, eat--t-write)
(eat--t-save-cur, eat--t-enable-alt-disp)
(eat--t-change-scroll-region, eat--t-set-sgr-params)
(eat--t-manipulate-selection, eat--t-handle-output)
(eat--t-resize, eat--flip-slow-blink-state)
(eat--flip-fast-blink-state, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-local-mode)
(eat--eshell-exec-visual, eat--trace-exec)
(eat--eshell-trace-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Combine multiple setq/setf/setq-local into one wherever
possible.
2022-11-28 21:54:55 +06:00
|
|
|
|
(setf (eat--t-term-scroll-begin eat--t-term) top
|
|
|
|
|
(eat--t-term-scroll-end eat--t-term) bottom)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat--t-goto 1 1))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-insert-mode ()
|
|
|
|
|
"Enable insert mode and disable replace mode."
|
|
|
|
|
(setf (eat--t-term-ins-mode eat--t-term) t))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-replace-mode ()
|
|
|
|
|
"Enable replace mode and disable insert mode."
|
|
|
|
|
(setf (eat--t-term-ins-mode eat--t-term) nil))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-set-sgr-params (params)
|
|
|
|
|
"Set SGR parameters PARAMS."
|
|
|
|
|
(let ((face (eat--t-term-face eat--t-term)))
|
|
|
|
|
;; Set attributes.
|
|
|
|
|
(while params
|
|
|
|
|
(pcase (pop params)
|
|
|
|
|
(`(,(or 0 'nil))
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(1value (setf (eat--t-face-fg face) nil))
|
|
|
|
|
(1value (setf (eat--t-face-bg face) nil))
|
|
|
|
|
(1value (setf (eat--t-face-intensity face) nil))
|
|
|
|
|
(1value (setf (eat--t-face-italic face) nil))
|
|
|
|
|
(1value (setf (eat--t-face-underline face) nil))
|
|
|
|
|
(1value (setf (eat--t-face-underline-color face) nil))
|
|
|
|
|
(1value (setf (eat--t-face-crossed face) nil))
|
|
|
|
|
(1value (setf (eat--t-face-conceal face) nil))
|
|
|
|
|
(1value (setf (eat--t-face-inverse face) nil))
|
|
|
|
|
(1value (setf (eat--t-face-blink face) nil))
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(setf (eat--t-face-font face)
|
|
|
|
|
(aref (eat--t-term-font-faces eat--t-term) 0)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
('(1)
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(setf (eat--t-face-intensity face)
|
|
|
|
|
(eat--t-term-bold-face eat--t-term)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
('(2)
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(setf (eat--t-face-intensity face)
|
|
|
|
|
(eat--t-term-faint-face eat--t-term)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
('(3)
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(setf (eat--t-face-italic face)
|
|
|
|
|
(eat--t-term-italic-face eat--t-term)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
('(4)
|
|
|
|
|
(1value (setf (eat--t-face-underline face) 'line)))
|
|
|
|
|
('(4 0)
|
|
|
|
|
(1value (setf (eat--t-face-underline face) nil)))
|
|
|
|
|
('(4 1)
|
|
|
|
|
(1value (setf (eat--t-face-underline face) 'line)))
|
|
|
|
|
('(4 2)
|
|
|
|
|
(1value (setf (eat--t-face-underline face) 'line)))
|
|
|
|
|
('(4 3)
|
|
|
|
|
(1value (setf (eat--t-face-underline face) 'wave)))
|
|
|
|
|
('(4 4)
|
|
|
|
|
(1value (setf (eat--t-face-underline face) 'wave)))
|
|
|
|
|
('(4 5)
|
|
|
|
|
(1value (setf (eat--t-face-underline face) 'wave)))
|
|
|
|
|
('(5)
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(setf (eat--t-face-blink face)
|
|
|
|
|
(eat--t-term-slow-blink-face eat--t-term)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
('(6)
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(setf (eat--t-face-blink face)
|
|
|
|
|
(eat--t-term-fast-blink-face eat--t-term)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
('(7)
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(1value (setf (eat--t-face-inverse face) t)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
('(8)
|
|
|
|
|
(1value (setf (eat--t-face-conceal face) t)))
|
|
|
|
|
('(9)
|
|
|
|
|
(1value (setf (eat--t-face-crossed face) t)))
|
|
|
|
|
(`(,(and (pred (lambda (font) (<= 10 font 19)))
|
|
|
|
|
font))
|
|
|
|
|
(setf (eat--t-face-font face)
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(aref (eat--t-term-font-faces eat--t-term)
|
|
|
|
|
(- font 10))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
('(21)
|
|
|
|
|
(1value (setf (eat--t-face-underline face) 'line)))
|
|
|
|
|
('(22)
|
|
|
|
|
(1value (setf (eat--t-face-intensity face) nil)))
|
|
|
|
|
('(23)
|
|
|
|
|
(1value (setf (eat--t-face-italic face) nil)))
|
|
|
|
|
('(24)
|
|
|
|
|
(1value (setf (eat--t-face-underline face) nil)))
|
|
|
|
|
('(25)
|
|
|
|
|
(1value (setf (eat--t-face-blink face) nil)))
|
|
|
|
|
('(27)
|
|
|
|
|
(1value (setf (eat--t-face-inverse face) nil)))
|
|
|
|
|
('(28)
|
|
|
|
|
(1value (setf (eat--t-face-conceal face) nil)))
|
|
|
|
|
('(29)
|
|
|
|
|
(1value (setf (eat--t-face-crossed face) nil)))
|
|
|
|
|
(`(,(and (pred (lambda (color) (<= 30 color 37)))
|
|
|
|
|
color))
|
|
|
|
|
(setf (eat--t-face-fg face)
|
|
|
|
|
(face-foreground
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(aref (eat--t-term-color-faces eat--t-term)
|
|
|
|
|
(- color 30))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
nil t)))
|
|
|
|
|
('(38)
|
|
|
|
|
(pcase (pop params)
|
|
|
|
|
('(2)
|
|
|
|
|
(setf (eat--t-face-fg face)
|
|
|
|
|
(let ((r (car (pop params)))
|
|
|
|
|
(g (car (pop params)))
|
|
|
|
|
(b (car (pop params))))
|
|
|
|
|
(when (and r (<= 0 r 255)
|
|
|
|
|
g (<= 0 g 255)
|
|
|
|
|
b (<= 0 b 255))
|
|
|
|
|
(format "#%02x%02x%02x" r g b)))))
|
|
|
|
|
('(5)
|
|
|
|
|
(let ((color (car (pop params))))
|
|
|
|
|
(setf (eat--t-face-fg face)
|
|
|
|
|
(when (and color (<= 0 color 255))
|
|
|
|
|
(face-foreground
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(aref (eat--t-term-color-faces eat--t-term)
|
|
|
|
|
color)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
nil t)))))))
|
|
|
|
|
('(39)
|
|
|
|
|
(1value (setf (eat--t-face-fg face) nil)))
|
|
|
|
|
(`(,(and (pred (lambda (color) (<= 40 color 47)))
|
|
|
|
|
color))
|
|
|
|
|
(setf (eat--t-face-bg face)
|
|
|
|
|
(face-foreground
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(aref (eat--t-term-color-faces eat--t-term)
|
|
|
|
|
(- color 40))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
nil t)))
|
|
|
|
|
('(48)
|
|
|
|
|
(setf (eat--t-face-bg face)
|
|
|
|
|
(pcase (pop params)
|
|
|
|
|
('(2)
|
|
|
|
|
(let ((r (car (pop params)))
|
|
|
|
|
(g (car (pop params)))
|
|
|
|
|
(b (car (pop params))))
|
|
|
|
|
(when (and r (<= 0 r 255)
|
|
|
|
|
g (<= 0 g 255)
|
|
|
|
|
b (<= 0 b 255))
|
|
|
|
|
(format "#%02x%02x%02x" r g b))))
|
|
|
|
|
('(5)
|
|
|
|
|
(let ((color (car (pop params))))
|
|
|
|
|
(when (and color (<= 0 color 255))
|
|
|
|
|
(face-foreground
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(aref (eat--t-term-color-faces eat--t-term)
|
|
|
|
|
color)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
nil t)))))))
|
|
|
|
|
('(49)
|
|
|
|
|
(1value (setf (eat--t-face-bg face) nil)))
|
|
|
|
|
('(58)
|
|
|
|
|
(setf (eat--t-face-underline-color face)
|
|
|
|
|
(pcase (pop params)
|
|
|
|
|
('(2)
|
|
|
|
|
(let ((r (car (pop params)))
|
|
|
|
|
(g (car (pop params)))
|
|
|
|
|
(b (car (pop params))))
|
|
|
|
|
(when (and r (<= 0 r 255)
|
|
|
|
|
g (<= 0 g 255)
|
|
|
|
|
b (<= 0 b 255))
|
|
|
|
|
(format "#%02x%02x%02x" r g b))))
|
|
|
|
|
('(5)
|
|
|
|
|
(let ((color (car (pop params))))
|
|
|
|
|
(when (and color (<= 0 color 255))
|
|
|
|
|
(face-foreground
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(aref (eat--t-term-color-faces eat--t-term)
|
|
|
|
|
color)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
nil t)))))))
|
|
|
|
|
('(59)
|
|
|
|
|
(1value (setf (eat--t-face-underline-color face) nil)))
|
|
|
|
|
(`(,(and (pred (lambda (color) (<= 90 color 97)))
|
|
|
|
|
color))
|
|
|
|
|
(setf (eat--t-face-fg face)
|
|
|
|
|
(face-foreground
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(aref (eat--t-term-color-faces eat--t-term)
|
|
|
|
|
(- color 82))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
nil t)))
|
|
|
|
|
(`(,(and (pred (lambda (color) (<= 100 color 107)))
|
|
|
|
|
color))
|
|
|
|
|
(setf (eat--t-face-bg face)
|
|
|
|
|
(face-foreground
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(aref (eat--t-term-color-faces eat--t-term)
|
|
|
|
|
(- color 92))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
nil t)))))
|
|
|
|
|
;; Update face according to the attributes.
|
|
|
|
|
(setf (eat--t-face-face face)
|
2022-11-28 23:22:52 +06:00
|
|
|
|
`(,@(and-let* ((fg (or (if (eat--t-face-conceal face)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat--t-face-bg face)
|
|
|
|
|
(eat--t-face-fg face))
|
|
|
|
|
(cond
|
|
|
|
|
((eat--t-face-inverse face)
|
|
|
|
|
(face-foreground 'default))
|
|
|
|
|
((eat--t-face-conceal face)
|
|
|
|
|
(face-background 'default))))))
|
|
|
|
|
(list (if (eat--t-face-inverse face)
|
|
|
|
|
:background
|
|
|
|
|
:foreground)
|
|
|
|
|
fg))
|
2022-11-28 23:22:52 +06:00
|
|
|
|
,@(and-let* ((bg (or (eat--t-face-bg face)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(and (eat--t-face-inverse face)
|
|
|
|
|
(face-background 'default)))))
|
|
|
|
|
(list (if (eat--t-face-inverse face)
|
|
|
|
|
:foreground
|
|
|
|
|
:background)
|
|
|
|
|
bg))
|
2022-11-28 23:22:52 +06:00
|
|
|
|
,@(and-let* ((underline (eat--t-face-underline face)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(list
|
|
|
|
|
:underline
|
|
|
|
|
(list :color (eat--t-face-underline-color face)
|
|
|
|
|
:style underline)))
|
2022-11-28 23:22:52 +06:00
|
|
|
|
,@(and-let* ((crossed (eat--t-face-crossed face)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; REVIEW: How about colors? No terminal supports
|
|
|
|
|
;; crossed attribute with colors, so we'll need to be
|
|
|
|
|
;; creative to add the feature.
|
|
|
|
|
`(:strike-through t))
|
|
|
|
|
:inherit
|
2022-11-28 23:22:52 +06:00
|
|
|
|
(,@(and-let* ((intensity (eat--t-face-intensity face)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(list intensity))
|
2022-11-28 23:22:52 +06:00
|
|
|
|
,@(and-let* ((italic (eat--t-face-italic face)))
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(list italic))
|
2022-11-28 23:22:52 +06:00
|
|
|
|
,@(and-let* ((blink (eat--t-face-blink face)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(list blink))
|
|
|
|
|
,(eat--t-face-font face))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-enable-keypad ()
|
|
|
|
|
"Enable keypad."
|
|
|
|
|
(1value (setf (eat--t-term-keypad-mode eat--t-term) t)))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-disable-keypad ()
|
|
|
|
|
"Disable keypad."
|
|
|
|
|
(1value (setf (eat--t-term-keypad-mode eat--t-term) nil)))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-enable-sgr-mouse-encoding ()
|
|
|
|
|
"Arrange that the following mouse events will be encoded like SGR."
|
|
|
|
|
(setf (eat--t-term-mouse-encoding eat--t-term) 'sgr))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-disable-sgr-mouse-encoding ()
|
|
|
|
|
"Arrange that the following mouse events won't be encoded like SGR."
|
|
|
|
|
(setf (eat--t-term-mouse-encoding eat--t-term) nil))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-set-mouse-mode (mode)
|
|
|
|
|
"Set current mouse mode to MODE.
|
|
|
|
|
|
|
|
|
|
MODE should be one of nil and `x10', `normal', `button-event',
|
|
|
|
|
`any-event'."
|
|
|
|
|
(setf (eat--t-term-mouse-mode eat--t-term) mode)
|
|
|
|
|
;; When MODE is nil, disable mouse.
|
|
|
|
|
(unless mode
|
|
|
|
|
(eat--t-disable-sgr-mouse-encoding))
|
|
|
|
|
;; `x10' mouse mode doesn't need to keep track of the mouse buttons
|
|
|
|
|
;; pressed.
|
|
|
|
|
(when (or (not mode)
|
|
|
|
|
(eq mode 'x10))
|
|
|
|
|
(setf (eat--t-term-mouse-pressed eat--t-term) nil))
|
|
|
|
|
;; Inform the UI.
|
|
|
|
|
(funcall (eat--t-term-grab-mouse-fn eat--t-term) eat--t-term
|
2022-11-28 22:29:15 +06:00
|
|
|
|
(pcase-exhaustive mode
|
2022-09-02 20:03:33 +06:00
|
|
|
|
('x10 :click)
|
|
|
|
|
('normal :modifier-click)
|
|
|
|
|
('button-event :drag)
|
2022-11-28 22:29:15 +06:00
|
|
|
|
('any-event :all)
|
|
|
|
|
('nil nil))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-enable-x10-mouse ()
|
|
|
|
|
"Enable X10 mouse tracking."
|
|
|
|
|
(eat--t-set-mouse-mode 'x10))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-enable-normal-mouse ()
|
|
|
|
|
"Enable normal mouse tracking."
|
|
|
|
|
(eat--t-set-mouse-mode 'normal))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-enable-button-event-mouse ()
|
|
|
|
|
"Enable button-event mouse tracking."
|
|
|
|
|
(eat--t-set-mouse-mode 'button-event))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-enable-any-event-mouse ()
|
|
|
|
|
"Enable any-event mouse tracking."
|
|
|
|
|
(eat--t-set-mouse-mode 'any-event))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-disable-mouse ()
|
|
|
|
|
"Disable mouse tracking."
|
|
|
|
|
(eat--t-set-mouse-mode nil))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-enable-focus-event ()
|
|
|
|
|
"Enable sending focus events."
|
|
|
|
|
(1value (setf (eat--t-term-focus-event-mode eat--t-term) t))
|
|
|
|
|
(funcall (eat--t-term-set-focus-ev-mode-fn eat--t-term) eat--t-term
|
|
|
|
|
t))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-disable-focus-event ()
|
|
|
|
|
"Disable sending focus events."
|
|
|
|
|
(1value (setf (eat--t-term-focus-event-mode eat--t-term) nil))
|
|
|
|
|
(funcall (eat--t-term-set-focus-ev-mode-fn eat--t-term) eat--t-term
|
|
|
|
|
nil))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-set-title (title)
|
|
|
|
|
"Set the title of terminal to TITLE."
|
|
|
|
|
;; Update title.
|
|
|
|
|
(setf (eat--t-term-title eat--t-term) title)
|
|
|
|
|
;; Inform the UI.
|
|
|
|
|
(funcall (eat--t-term-set-title-fn eat--t-term) eat--t-term title))
|
|
|
|
|
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
(defun eat--t-set-cwd (format host path)
|
2022-12-01 01:40:17 +06:00
|
|
|
|
"Set the working directory of terminal to URL.
|
|
|
|
|
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
If FORMAT is `base64', HOST should be base64 encoded hostname and PATH
|
|
|
|
|
should be base64 encoded working directory path.
|
|
|
|
|
|
|
|
|
|
If FORMAT is `url', HOST should be nil and PATH should be an URL in
|
|
|
|
|
the format \"file://HOST/CWD/\"; HOST can be empty."
|
|
|
|
|
(pcase-exhaustive format
|
|
|
|
|
('base64
|
|
|
|
|
(let ((dir (ignore-errors (expand-file-name
|
|
|
|
|
(file-name-as-directory
|
2022-12-16 14:48:24 +06:00
|
|
|
|
(decode-coding-string
|
|
|
|
|
(base64-decode-string path)
|
|
|
|
|
locale-coding-system)))))
|
|
|
|
|
(hostname (ignore-errors (decode-coding-string
|
|
|
|
|
(base64-decode-string host)
|
|
|
|
|
locale-coding-system))))
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
(when (and dir hostname)
|
|
|
|
|
;; Update working directory.
|
|
|
|
|
(setf (eat--t-term-cwd eat--t-term) (cons hostname dir))
|
|
|
|
|
;; Inform the UI.
|
|
|
|
|
(funcall (eat--t-term-set-cwd-fn eat--t-term)
|
|
|
|
|
eat--t-term hostname dir))))
|
|
|
|
|
('url
|
|
|
|
|
(let ((url (url-generic-parse-url path)))
|
|
|
|
|
(when (string= (url-type url) "file")
|
|
|
|
|
(let ((host (url-host url))
|
|
|
|
|
(dir (expand-file-name
|
|
|
|
|
(file-name-as-directory
|
|
|
|
|
(url-unhex-string (url-filename url))))))
|
|
|
|
|
;; Update working directory.
|
|
|
|
|
(setf (eat--t-term-cwd eat--t-term) (cons host dir))
|
|
|
|
|
;; Inform the UI.
|
|
|
|
|
(funcall (eat--t-term-set-cwd-fn eat--t-term)
|
|
|
|
|
eat--t-term host dir)))))))
|
2022-12-01 01:40:17 +06:00
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defun eat--t-send-device-attrs (params format)
|
|
|
|
|
"Return device attributes.
|
|
|
|
|
|
|
|
|
|
PARAMS is the parameter list and FORMAT is the format of parameters in
|
|
|
|
|
output."
|
2022-11-28 22:29:15 +06:00
|
|
|
|
(pcase-exhaustive format
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
('nil
|
2022-12-28 22:01:36 +06:00
|
|
|
|
(when (= (or (caar params) 1) 0)
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(funcall (eat--t-term-input-fn eat--t-term) eat--t-term
|
|
|
|
|
"\e[?1;2c")))
|
|
|
|
|
(?>
|
2022-12-28 22:01:36 +06:00
|
|
|
|
(when (= (or (caar params) 1) 0)
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(funcall (eat--t-term-input-fn eat--t-term) eat--t-term
|
|
|
|
|
"\e[>0;242;0c")))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-report-foreground-color ()
|
|
|
|
|
"Report the current default foreground color to the client."
|
|
|
|
|
(funcall
|
|
|
|
|
(eat--t-term-input-fn eat--t-term) eat--t-term
|
2022-12-09 20:44:08 +06:00
|
|
|
|
(let ((rgb (or (color-values (face-foreground 'default))
|
|
|
|
|
;; On terminals like TTYs the above returns nil.
|
|
|
|
|
;; Terminals usually have a white foreground, so...
|
|
|
|
|
'(255 255 255))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(format "\e]10;%04x/%04x/%04x\e\\"
|
|
|
|
|
(pop rgb) (pop rgb) (pop rgb)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-report-background-color ()
|
|
|
|
|
"Report the current default background color to the client."
|
|
|
|
|
(funcall
|
|
|
|
|
(eat--t-term-input-fn eat--t-term) eat--t-term
|
2022-12-09 20:44:08 +06:00
|
|
|
|
(let ((rgb (or (color-values (face-background 'default))
|
|
|
|
|
;; On terminals like TTYs the above returns nil.
|
|
|
|
|
;; Terminals usually have a black background, so...
|
|
|
|
|
'(0 0 0))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(format "\e]11;%04x/%04x/%04x\e\\"
|
|
|
|
|
(pop rgb) (pop rgb) (pop rgb)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-manipulate-selection (targets data)
|
|
|
|
|
"Set and send current selection.
|
|
|
|
|
|
|
|
|
|
TARGETS is a string containing zero or more characters from the set
|
2023-03-28 13:58:43 +06:00
|
|
|
|
`c', `p', `q', `s', `0', `1', `2', `3', `4', `5', `6', and `7'. DATA
|
|
|
|
|
is the selection data encoded in base64."
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when (string-empty-p targets)
|
|
|
|
|
(setq targets "s0"))
|
|
|
|
|
(if (string= data "?")
|
|
|
|
|
;; The client is requesting for clipboard content, let's try to
|
|
|
|
|
;; fulfill the request.
|
|
|
|
|
(funcall
|
|
|
|
|
(eat--t-term-input-fn eat--t-term) eat--t-term
|
|
|
|
|
(let ((str nil)
|
|
|
|
|
(n 0))
|
2023-03-28 13:58:43 +06:00
|
|
|
|
;; Remove invalid and duplicate targets from TARGETS before
|
|
|
|
|
;; processing it and sending it back.
|
|
|
|
|
(setq targets
|
|
|
|
|
(apply #'string
|
|
|
|
|
(cl-delete-duplicates
|
|
|
|
|
(cl-delete-if-not
|
|
|
|
|
(lambda (c) (or (<= ?0 c ?7)
|
|
|
|
|
(memq c '(?c ?p ?q ?s))))
|
|
|
|
|
(string-to-list targets)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(while (and (not str) (< n (length targets)))
|
|
|
|
|
(setq
|
|
|
|
|
str
|
|
|
|
|
(pcase (aref targets n)
|
|
|
|
|
;; c, p, q and s targets are handled by the UI, and they
|
|
|
|
|
;; might refuse to give the clipboard content.
|
|
|
|
|
(?c
|
|
|
|
|
(funcall
|
|
|
|
|
(eat--t-term-manipulate-selection-fn eat--t-term)
|
|
|
|
|
eat--t-term :clipboard t))
|
|
|
|
|
(?p
|
|
|
|
|
(funcall
|
|
|
|
|
(eat--t-term-manipulate-selection-fn eat--t-term)
|
|
|
|
|
eat--t-term :primary t))
|
|
|
|
|
(?q
|
|
|
|
|
(funcall
|
|
|
|
|
(eat--t-term-manipulate-selection-fn eat--t-term)
|
|
|
|
|
eat--t-term :secondary t))
|
|
|
|
|
(?s
|
|
|
|
|
(funcall
|
|
|
|
|
(eat--t-term-manipulate-selection-fn eat--t-term)
|
|
|
|
|
eat--t-term :select t))
|
|
|
|
|
;; 0 to 9 targets are handled by us, and always work.
|
|
|
|
|
((and (pred (<= ?0))
|
2023-03-28 13:58:43 +06:00
|
|
|
|
(pred (>= ?7))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
i)
|
|
|
|
|
(aref (eat--t-term-cut-buffers eat--t-term)
|
|
|
|
|
(- i ?0)))))
|
|
|
|
|
(cl-incf n))
|
2023-03-28 13:58:43 +06:00
|
|
|
|
;; No string to send, so send an empty string.
|
|
|
|
|
(unless str (setq str ""))
|
|
|
|
|
(format "\e]52;%s;%s\e\\" targets
|
|
|
|
|
(base64-encode-string (encode-coding-string
|
|
|
|
|
str locale-coding-system)
|
|
|
|
|
'no-line-break))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; The client is requesting to set clipboard content, let's try to
|
|
|
|
|
;; fulfill the request.
|
2022-12-16 14:48:24 +06:00
|
|
|
|
(let ((str (ignore-errors
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(decode-coding-string (base64-decode-string data)
|
|
|
|
|
locale-coding-system))))
|
|
|
|
|
(seq-doseq (target targets)
|
|
|
|
|
(pcase target
|
|
|
|
|
;; c, p, q and s targets are handled by the UI, and they
|
|
|
|
|
;; might reject the new clipboard content.
|
|
|
|
|
(?c
|
|
|
|
|
(funcall (eat--t-term-manipulate-selection-fn eat--t-term)
|
|
|
|
|
eat--t-term :clipboard str))
|
|
|
|
|
(?p
|
|
|
|
|
(funcall (eat--t-term-manipulate-selection-fn eat--t-term)
|
|
|
|
|
eat--t-term :primary str))
|
|
|
|
|
(?q
|
|
|
|
|
(funcall (eat--t-term-manipulate-selection-fn eat--t-term)
|
|
|
|
|
eat--t-term :secondary str))
|
|
|
|
|
(?s
|
|
|
|
|
(funcall (eat--t-term-manipulate-selection-fn eat--t-term)
|
|
|
|
|
eat--t-term :select str))
|
2023-03-28 13:58:43 +06:00
|
|
|
|
;; 0 to 7 targets are handled by us, and always work.
|
2022-09-02 20:03:33 +06:00
|
|
|
|
((and (pred (<= ?0))
|
2023-03-28 13:58:43 +06:00
|
|
|
|
(pred (>= ?7))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
i)
|
|
|
|
|
(aset (eat--t-term-cut-buffers eat--t-term) (- i ?0)
|
|
|
|
|
str)))))))
|
|
|
|
|
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
(defun eat--t-prompt-start ()
|
|
|
|
|
"Call shell prompt start hook."
|
|
|
|
|
(funcall (eat--t-term-prompt-start-fn eat--t-term) eat--t-term))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-prompt-end ()
|
|
|
|
|
"Call shell prompt end hook."
|
|
|
|
|
(funcall (eat--t-term-prompt-end-fn eat--t-term) eat--t-term))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-cont-prompt-start ()
|
|
|
|
|
"Call shell prompt start hook."
|
|
|
|
|
(funcall (eat--t-term-cont-prompt-start-fn eat--t-term)
|
|
|
|
|
eat--t-term))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-cont-prompt-end ()
|
|
|
|
|
"Call shell prompt end hook."
|
|
|
|
|
(funcall (eat--t-term-cont-prompt-end-fn eat--t-term) eat--t-term))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-set-cmd (cmd)
|
|
|
|
|
"Set the command being executed to CMD."
|
2022-12-16 14:48:24 +06:00
|
|
|
|
(when-let* ((c (ignore-errors (decode-coding-string
|
|
|
|
|
(base64-decode-string cmd)
|
|
|
|
|
locale-coding-system))))
|
|
|
|
|
(funcall (eat--t-term-set-cmd-fn eat--t-term) eat--t-term c)))
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-cmd-start ()
|
|
|
|
|
"Call shell command start hook."
|
|
|
|
|
(funcall (eat--t-term-cmd-start-fn eat--t-term) eat--t-term))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-cmd-finish (status)
|
|
|
|
|
"Call shell command finish hook with exit status STATUS."
|
|
|
|
|
(funcall (eat--t-term-cmd-finish-fn eat--t-term) eat--t-term
|
|
|
|
|
status))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defun eat--t-set-modes (params format)
|
|
|
|
|
"Set modes according to PARAMS in format FORMAT."
|
|
|
|
|
;; Dispatch the request to appropriate function.
|
|
|
|
|
(pcase format
|
|
|
|
|
('nil
|
|
|
|
|
(while params
|
|
|
|
|
(pcase (pop params)
|
|
|
|
|
('(4)
|
|
|
|
|
(eat--t-insert-mode)))))
|
|
|
|
|
(??
|
|
|
|
|
(while params
|
|
|
|
|
(pcase (pop params)
|
|
|
|
|
('(1)
|
|
|
|
|
(eat--t-enable-keypad))
|
|
|
|
|
('(7)
|
|
|
|
|
(eat--t-enable-auto-margin))
|
|
|
|
|
('(9)
|
|
|
|
|
(eat--t-enable-x10-mouse))
|
|
|
|
|
('(12)
|
|
|
|
|
(eat--t-blinking-cursor))
|
|
|
|
|
('(25)
|
|
|
|
|
(eat--t-default-cursor))
|
|
|
|
|
('(1000)
|
|
|
|
|
(eat--t-enable-normal-mouse))
|
|
|
|
|
('(1002)
|
|
|
|
|
(eat--t-enable-button-event-mouse))
|
|
|
|
|
('(1003)
|
|
|
|
|
(eat--t-enable-any-event-mouse))
|
|
|
|
|
('(1004)
|
|
|
|
|
(eat--t-enable-focus-event))
|
|
|
|
|
('(1006)
|
|
|
|
|
(eat--t-enable-sgr-mouse-encoding))
|
|
|
|
|
('(1048)
|
|
|
|
|
(eat--t-save-cur))
|
|
|
|
|
(`(,(or 1047 1049))
|
|
|
|
|
(eat--t-enable-alt-disp))
|
|
|
|
|
('(2004)
|
|
|
|
|
(eat--t-enable-bracketed-yank)))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-reset-modes (params format)
|
|
|
|
|
"Reset modes according to PARAMS in format FORMAT."
|
|
|
|
|
;; Dispatch the request to appropriate function.
|
|
|
|
|
(pcase format
|
|
|
|
|
('nil
|
|
|
|
|
(while params
|
|
|
|
|
(pcase (pop params)
|
|
|
|
|
('(4)
|
|
|
|
|
(eat--t-replace-mode)))))
|
|
|
|
|
(??
|
|
|
|
|
(while params
|
|
|
|
|
(pcase (pop params)
|
|
|
|
|
('(1)
|
|
|
|
|
(eat--t-disable-keypad))
|
|
|
|
|
('(7)
|
|
|
|
|
(eat--t-disable-auto-margin))
|
|
|
|
|
('(12)
|
|
|
|
|
(eat--t-non-blinking-cursor))
|
|
|
|
|
('(25)
|
|
|
|
|
(eat--t-invisible-cursor))
|
|
|
|
|
(`(,(or 9 1000 1002 1003))
|
|
|
|
|
(eat--t-disable-mouse))
|
|
|
|
|
('(1004)
|
|
|
|
|
(eat--t-disable-focus-event))
|
|
|
|
|
('(1006)
|
|
|
|
|
(eat--t-disable-sgr-mouse-encoding))
|
|
|
|
|
('(1047)
|
|
|
|
|
(eat--t-disable-alt-disp 'dont-move-cursor))
|
|
|
|
|
('(1048)
|
|
|
|
|
(eat--t-restore-cur))
|
|
|
|
|
('(1049)
|
|
|
|
|
(eat--t-disable-alt-disp))
|
|
|
|
|
('(2004)
|
|
|
|
|
(eat--t-disable-bracketed-yank)))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--t-handle-output (output)
|
|
|
|
|
"Parse and evaluate OUTPUT."
|
|
|
|
|
(let ((index 0))
|
2022-12-15 20:18:04 +06:00
|
|
|
|
(while (/= index (length output))
|
2022-11-28 22:29:15 +06:00
|
|
|
|
(pcase-exhaustive (eat--t-term-parser-state eat--t-term)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
('nil
|
2022-12-15 20:18:04 +06:00
|
|
|
|
(let ((ins-beg index))
|
|
|
|
|
(while (and (/= index (length output))
|
|
|
|
|
(not (memq (aref output index)
|
|
|
|
|
'( ?\0 ?\a ?\b ?\t ?\n ?\v ?\f ?\r
|
|
|
|
|
?\C-n ?\C-o ?\e #x7f))))
|
|
|
|
|
(cl-incf index))
|
|
|
|
|
(when (/= ins-beg index)
|
|
|
|
|
;; Insert.
|
|
|
|
|
(eat--t-write output ins-beg index))
|
|
|
|
|
(when (/= index (length output))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Dispatch control sequence.
|
|
|
|
|
(cl-incf index)
|
2022-12-20 10:49:02 +06:00
|
|
|
|
(pcase (aref output (1- index))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(?\a
|
|
|
|
|
(eat--t-bell))
|
|
|
|
|
(?\b
|
|
|
|
|
(eat--t-cur-left 1))
|
|
|
|
|
(?\t
|
|
|
|
|
(eat--t-horizontal-tab 1))
|
|
|
|
|
(?\n
|
|
|
|
|
(eat--t-line-feed))
|
|
|
|
|
(?\v
|
|
|
|
|
(eat--t-index))
|
|
|
|
|
(?\f
|
|
|
|
|
(eat--t-form-feed))
|
|
|
|
|
(?\r
|
|
|
|
|
;; Avoid going to line home just before a line feed,
|
|
|
|
|
;; we can just insert a new line if we are at the
|
|
|
|
|
;; end of display.
|
|
|
|
|
(unless (and (/= index (length output))
|
|
|
|
|
(= (aref output index) ?\n))
|
|
|
|
|
(eat--t-carriage-return)))
|
|
|
|
|
(?\C-n
|
|
|
|
|
(eat--t-change-charset 'g1))
|
|
|
|
|
(?\C-o
|
|
|
|
|
(eat--t-change-charset 'g0))
|
|
|
|
|
(?\e
|
|
|
|
|
(1value (setf (eat--t-term-parser-state eat--t-term)
|
2022-12-20 10:49:02 +06:00
|
|
|
|
'(read-esc))))
|
|
|
|
|
;; Others are ignored.
|
|
|
|
|
))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
('(read-esc)
|
|
|
|
|
(let ((type (aref output index)))
|
|
|
|
|
(cl-incf index)
|
|
|
|
|
(1value (setf (eat--t-term-parser-state eat--t-term) nil))
|
|
|
|
|
;; Dispatch control sequence.
|
|
|
|
|
(pcase type
|
|
|
|
|
;; ESC (.
|
|
|
|
|
(?\(
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
'(read-charset-standard g0 "")))
|
|
|
|
|
;; ESC ).
|
|
|
|
|
(?\)
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
'(read-charset-standard g1 "")))
|
|
|
|
|
;; ESC *.
|
|
|
|
|
(?*
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
'(read-charset-standard g2 "")))
|
|
|
|
|
;; ESC +.
|
|
|
|
|
(?+
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
'(read-charset-standard g3 "")))
|
|
|
|
|
;; ESC -.
|
|
|
|
|
(?-
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
'(read-charset-vt300 g1 "")))
|
|
|
|
|
;; ESC ..
|
|
|
|
|
(?.
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
'(read-charset-vt300 g2 "")))
|
|
|
|
|
;; ESC /.
|
|
|
|
|
(?/
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
'(read-charset-vt300 g3 "")))
|
|
|
|
|
;; ESC 7.
|
|
|
|
|
(?7
|
|
|
|
|
(eat--t-save-cur))
|
|
|
|
|
;; ESC 8.
|
|
|
|
|
(?8
|
|
|
|
|
(eat--t-restore-cur))
|
|
|
|
|
;; ESC D.
|
|
|
|
|
(?D
|
|
|
|
|
(eat--t-index))
|
|
|
|
|
;; ESC E.
|
|
|
|
|
(?E
|
|
|
|
|
(eat--t-line-feed))
|
|
|
|
|
;; ESC M.
|
|
|
|
|
(?M
|
|
|
|
|
(eat--t-reverse-index))
|
|
|
|
|
;; ESC P, or DCS.
|
|
|
|
|
(?P
|
|
|
|
|
(1value (setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
'(read-dcs ""))))
|
|
|
|
|
;; ESC X, or SOS.
|
|
|
|
|
(?X
|
|
|
|
|
(1value (setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
'(read-sos ""))))
|
|
|
|
|
;; ESC [, or CSI.
|
|
|
|
|
(?\[
|
|
|
|
|
(1value (setf (eat--t-term-parser-state eat--t-term)
|
2022-12-15 20:18:04 +06:00
|
|
|
|
'(read-csi-format))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; ESC ], or OSC.
|
|
|
|
|
(?\]
|
|
|
|
|
(1value (setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
'(read-osc ""))))
|
|
|
|
|
;; ESC ^, or PM.
|
|
|
|
|
(?^
|
|
|
|
|
(1value (setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
'(read-pm ""))))
|
|
|
|
|
;; ESC _, or APC.
|
|
|
|
|
(?_
|
|
|
|
|
(1value (setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
'(read-apc ""))))
|
|
|
|
|
;; ESC c.
|
|
|
|
|
(?c
|
|
|
|
|
(eat--t-reset))
|
|
|
|
|
;; ESC n.
|
|
|
|
|
(?n
|
|
|
|
|
(eat--t-change-charset 'g2))
|
|
|
|
|
;; ESC o.
|
|
|
|
|
(?o
|
|
|
|
|
(eat--t-change-charset 'g3)))))
|
2022-12-15 20:18:04 +06:00
|
|
|
|
('(read-csi-format)
|
|
|
|
|
(let ((format nil))
|
|
|
|
|
(pcase (aref output index)
|
|
|
|
|
(??
|
|
|
|
|
(setq format ??)
|
|
|
|
|
(cl-incf index))
|
|
|
|
|
(?>
|
|
|
|
|
(setq format ?>)
|
|
|
|
|
(cl-incf index))
|
|
|
|
|
(?=
|
|
|
|
|
(setq format ?=)
|
|
|
|
|
(cl-incf index)))
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
`(read-csi-params ,format ,(list (list nil))))))
|
|
|
|
|
(`(read-csi-params ,format ,params)
|
|
|
|
|
;; Interpretion of the parameter depends on `format' and
|
|
|
|
|
;; other things (including things we haven't got yet)
|
|
|
|
|
;; according to the standard. We don't recognize any other
|
|
|
|
|
;; format of parameters, so we can skip any checks.
|
|
|
|
|
(let ((loop t))
|
|
|
|
|
(while loop
|
|
|
|
|
(cond
|
|
|
|
|
((= index (length output))
|
|
|
|
|
;; Output exhausted. We need to wait for more.
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
`(read-csi-params ,format ,params))
|
|
|
|
|
(setq loop nil))
|
|
|
|
|
((not (<= ?0 (aref output index) ?\;))
|
|
|
|
|
;; End of parameters.
|
|
|
|
|
;; NOTE: All parameter and their parts are in reverse
|
|
|
|
|
;; order!
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
`(read-csi-function ,format ,params nil))
|
|
|
|
|
(setq loop nil))
|
|
|
|
|
(t
|
|
|
|
|
(cond
|
|
|
|
|
((= (aref output index) ?:)
|
|
|
|
|
;; New parameter substring.
|
|
|
|
|
(push nil (car params)))
|
|
|
|
|
((= (aref output index) ?\;)
|
|
|
|
|
;; New parameter.
|
|
|
|
|
(push (list nil) params))
|
|
|
|
|
(t ; (<= ?0 (aref output index) ?9)
|
|
|
|
|
;; Number, save it.
|
|
|
|
|
(setf (caar params)
|
|
|
|
|
(+ (* (or (caar params) 0) 10)
|
|
|
|
|
(- (aref output index) #x30)))))
|
|
|
|
|
(cl-incf index))))))
|
|
|
|
|
(`(read-csi-function ,format ,params ,function)
|
|
|
|
|
(let ((loop t))
|
|
|
|
|
(while loop
|
|
|
|
|
(cond
|
|
|
|
|
((= index (length output))
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
`(read-csi-function ,format ,params ,function))
|
|
|
|
|
(setq loop nil)))
|
|
|
|
|
(push (aref output index) function)
|
|
|
|
|
(cl-incf index)
|
|
|
|
|
(when (<= ?@ (car function) ?~)
|
|
|
|
|
;; Now we have enough information to execute it!
|
|
|
|
|
(setq loop nil)
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term) nil)
|
|
|
|
|
;; NOTE: `function' and `params' are in reverse order!
|
|
|
|
|
(pcase (list function format params)
|
|
|
|
|
;; CSI <n> @.
|
|
|
|
|
(`((?@) nil ((,n)))
|
|
|
|
|
(eat--t-insert-char n))
|
|
|
|
|
;; CSI <n> A.
|
|
|
|
|
;; CSI <n> k.
|
|
|
|
|
(`((,(or ?A ?k)) nil ((,n)))
|
|
|
|
|
(eat--t-cur-up n))
|
|
|
|
|
;; CSI <n> B.
|
|
|
|
|
;; CSI <n> e.
|
|
|
|
|
(`((,(or ?B ?e)) nil ((,n)))
|
|
|
|
|
(eat--t-cur-down n))
|
|
|
|
|
;; CSI <n> C.
|
|
|
|
|
;; CSI <n> a.
|
|
|
|
|
(`((,(or ?C ?a)) nil ((,n)))
|
|
|
|
|
(eat--t-cur-right n))
|
|
|
|
|
;; CSI <n> D.
|
|
|
|
|
;; CSI <n> j.
|
|
|
|
|
(`((,(or ?D ?j)) nil ((,n)))
|
|
|
|
|
(eat--t-cur-left n))
|
|
|
|
|
;; CSI <n> E.
|
|
|
|
|
(`((?E) nil ((,n)))
|
|
|
|
|
(eat--t-beg-of-prev-line n))
|
|
|
|
|
;; CSI <n> F.
|
|
|
|
|
(`((?F) nil ((,n)))
|
|
|
|
|
(eat--t-beg-of-next-line n))
|
|
|
|
|
;; CSI <n> G.
|
|
|
|
|
;; CSI <n> `.
|
|
|
|
|
(`((,(or ?G ?`)) nil ((,n)))
|
|
|
|
|
(eat--t-cur-horizontal-abs n))
|
|
|
|
|
;; CSI <n> ; <m> H
|
|
|
|
|
;; CSI <n> ; <m> f
|
|
|
|
|
(`((,(or ?H ?f)) nil ,(and (pred listp) params))
|
|
|
|
|
(eat--t-goto (caadr params) (caar params)))
|
|
|
|
|
;; CSI <n> I.
|
|
|
|
|
(`((?I) nil ((,n)))
|
|
|
|
|
(eat--t-horizontal-tab n))
|
|
|
|
|
;; CSI <n> J.
|
|
|
|
|
(`((?J) nil ((,n)))
|
|
|
|
|
(eat--t-erase-in-disp n))
|
|
|
|
|
;; CSI <n> K.
|
|
|
|
|
(`((?K) nil ((,n)))
|
|
|
|
|
(eat--t-erase-in-line n))
|
|
|
|
|
;; CSI <n> L.
|
|
|
|
|
(`((?L) nil ((,n)))
|
|
|
|
|
(eat--t-insert-line n))
|
|
|
|
|
;; CSI <n> M.
|
|
|
|
|
(`((?M) nil ((,n)))
|
|
|
|
|
(eat--t-delete-line n))
|
|
|
|
|
;; CSI <n> P.
|
|
|
|
|
(`((?P) nil ((,n)))
|
|
|
|
|
(eat--t-delete-char n))
|
|
|
|
|
;; CSI <n> S.
|
|
|
|
|
(`((?S) nil ((,n)))
|
|
|
|
|
(eat--t-scroll-up n))
|
|
|
|
|
;; CSI <n> T.
|
|
|
|
|
(`((?T) nil ((,n)))
|
|
|
|
|
(eat--t-scroll-down n))
|
|
|
|
|
;; CSI <n> X.
|
|
|
|
|
(`((?X) nil ((,n)))
|
|
|
|
|
(eat--t-erase-char n))
|
|
|
|
|
;; CSI <n> Z.
|
|
|
|
|
(`((?Z) nil ((,n)))
|
|
|
|
|
(eat--t-horizontal-backtab n))
|
|
|
|
|
;; CSI <n> b.
|
|
|
|
|
(`((?b) nil ((,n)))
|
|
|
|
|
(eat--t-repeat-last-char n))
|
|
|
|
|
;; CSI <n> c.
|
|
|
|
|
;; CSI > <n> c.
|
|
|
|
|
(`((?c) ,format ,(and (pred listp) params))
|
|
|
|
|
;; Reverse `params' to get it into the correct
|
|
|
|
|
;; order.
|
|
|
|
|
(setq params (nreverse params))
|
|
|
|
|
(let ((p params))
|
|
|
|
|
(while p
|
|
|
|
|
(setf (car p) (nreverse (car p)))
|
|
|
|
|
(setq p (cdr p))))
|
|
|
|
|
;; TODO: This function kinda a HACK.
|
|
|
|
|
(eat--t-send-device-attrs params format))
|
|
|
|
|
;; CSI <n> d.
|
|
|
|
|
(`((?d) nil ((,n)))
|
|
|
|
|
(eat--t-cur-vertical-abs n))
|
|
|
|
|
;; CSI ... h.
|
|
|
|
|
;; CSI ? ... h.
|
|
|
|
|
(`((?h) ,format ,(and (pred listp) params))
|
|
|
|
|
;; Reverse `params' to get it into the correct
|
|
|
|
|
;; order.
|
|
|
|
|
(setq params (nreverse params))
|
|
|
|
|
(let ((p params))
|
|
|
|
|
(while p
|
|
|
|
|
(setf (car p) (nreverse (car p)))
|
|
|
|
|
(setq p (cdr p))))
|
|
|
|
|
(eat--t-set-modes params format))
|
|
|
|
|
;; CSI ... l.
|
|
|
|
|
;; CSI ? ... l.
|
|
|
|
|
(`((?l) ,format ,(and (pred listp) params))
|
|
|
|
|
;; Reverse `params' to get it into the correct
|
|
|
|
|
;; order.
|
|
|
|
|
(setq params (nreverse params))
|
|
|
|
|
(let ((p params))
|
|
|
|
|
(while p
|
|
|
|
|
(setf (car p) (nreverse (car p)))
|
|
|
|
|
(setq p (cdr p))))
|
|
|
|
|
(eat--t-reset-modes params format))
|
|
|
|
|
;; CSI ... m.
|
|
|
|
|
(`((?m) nil ,(and (pred listp) params))
|
|
|
|
|
;; Reverse `params' to get it into the correct
|
|
|
|
|
;; order.
|
|
|
|
|
(setq params (nreverse params))
|
|
|
|
|
(let ((p params))
|
|
|
|
|
(while p
|
|
|
|
|
(setf (car p) (nreverse (car p)))
|
|
|
|
|
(setq p (cdr p))))
|
|
|
|
|
(eat--t-set-sgr-params params))
|
|
|
|
|
;; CSI 6 n.
|
|
|
|
|
('((?n) nil ((6)))
|
|
|
|
|
(eat--t-device-status-report))
|
|
|
|
|
;; CSI <n> ; <n> r.
|
|
|
|
|
(`((?r) nil ,(and (pred listp) params))
|
|
|
|
|
(eat--t-change-scroll-region (caadr params)
|
|
|
|
|
(caar params)))
|
|
|
|
|
;; CSI s.
|
|
|
|
|
(`((?s) nil nil)
|
|
|
|
|
(eat--t-save-cur))
|
|
|
|
|
;; CSI u.
|
|
|
|
|
(`((?u) nil nil)
|
|
|
|
|
(eat--t-restore-cur)))))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(`(,(and (or 'read-dcs 'read-sos 'read-osc 'read-pm 'read-apc)
|
|
|
|
|
state)
|
|
|
|
|
,buf)
|
|
|
|
|
;; Find the end of string.
|
|
|
|
|
(let ((match (string-match (if (eq state 'read-osc)
|
|
|
|
|
(rx (or ?\a ?\\))
|
|
|
|
|
(rx ?\\))
|
|
|
|
|
output index)))
|
|
|
|
|
(if (not match)
|
|
|
|
|
(progn
|
|
|
|
|
;; Not found, store the text to process it later when
|
|
|
|
|
;; we get the end of string.
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
`(,state ,(concat buf (substring output
|
|
|
|
|
index))))
|
|
|
|
|
(setq index (length output)))
|
|
|
|
|
;; Matched! Get the string from the output and previous
|
|
|
|
|
;; runs.
|
|
|
|
|
(let ((str (concat buf (substring output index
|
|
|
|
|
match))))
|
|
|
|
|
(setq index (match-end 0))
|
|
|
|
|
;; Is it really the end of string?
|
|
|
|
|
(if (and (= (aref output match) ?\\)
|
|
|
|
|
(not (or (zerop (length str))
|
|
|
|
|
(= (aref str (1- (length str)))
|
|
|
|
|
?\e))))
|
|
|
|
|
;; No. Push the '\' character to process later.
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
`(,state ,(concat str "\\")))
|
|
|
|
|
;; Yes! It's the end! We can parse it.
|
|
|
|
|
(when (= (aref output match) ?\\)
|
|
|
|
|
(setq str (substring str 0 (1- (length str)))))
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term) nil)
|
|
|
|
|
;; Dispatch control sequence.
|
|
|
|
|
(pcase state
|
|
|
|
|
('read-osc
|
|
|
|
|
(pcase str
|
|
|
|
|
;; OSC 0 ; <t> ST.
|
|
|
|
|
;; OSC 2 ; <t> ST.
|
|
|
|
|
((rx string-start (or ?0 ?2) ?\;
|
|
|
|
|
(let title (zero-or-more anything))
|
|
|
|
|
string-end)
|
|
|
|
|
(eat--t-set-title title))
|
2022-12-01 01:40:17 +06:00
|
|
|
|
;; OSC 7 ; <t> ST.
|
|
|
|
|
((rx string-start ?7 ?\;
|
|
|
|
|
(let url (zero-or-more anything))
|
|
|
|
|
string-end)
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
(eat--t-set-cwd 'url nil url))
|
|
|
|
|
;; OSC 1 0 ; ? ST.
|
2022-09-02 20:03:33 +06:00
|
|
|
|
("10;?"
|
|
|
|
|
(eat--t-report-foreground-color))
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
;; OSC 1 1 ; ? ST.
|
2022-09-02 20:03:33 +06:00
|
|
|
|
("11;?"
|
|
|
|
|
(eat--t-report-background-color))
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
;; In XTerm, OSC 51 is reserved for Emacs shell.
|
|
|
|
|
;; I have no idea why, but Vterm uses this OSC
|
|
|
|
|
;; to set the current directory and remotely
|
|
|
|
|
;; execute Emacs Lisp code. Vterm uses the
|
|
|
|
|
;; characters 'A' and 'E' as the first character
|
|
|
|
|
;; of second parameter of this OSC. We use 'e'
|
|
|
|
|
;; as the second parameter, followed by one or
|
|
|
|
|
;; more parameters.
|
|
|
|
|
;; OSC 5 1 ; e ; A ; <t> ; <s> ST
|
|
|
|
|
((rx string-start "51;e;A;"
|
|
|
|
|
(let host (zero-or-more (not ?\;)))
|
|
|
|
|
?\; (let path (zero-or-more anything))
|
|
|
|
|
string-end)
|
|
|
|
|
(eat--t-set-cwd 'base64 host path))
|
|
|
|
|
;; OSC 5 1 ; e ; B ST
|
|
|
|
|
("51;e;B"
|
|
|
|
|
(eat--t-prompt-start))
|
|
|
|
|
;; OSC 5 1 ; e ; C ST
|
|
|
|
|
("51;e;C"
|
|
|
|
|
(eat--t-prompt-end))
|
|
|
|
|
;; OSC 5 1 ; e ; D ST
|
|
|
|
|
("51;e;D"
|
|
|
|
|
(eat--t-cont-prompt-start))
|
|
|
|
|
;; OSC 5 1 ; e ; E ST
|
|
|
|
|
("51;e;E"
|
|
|
|
|
(eat--t-cont-prompt-end))
|
|
|
|
|
;; OSC 5 1 ; e ; F ; <t> ST
|
|
|
|
|
((rx string-start "51;e;F;"
|
|
|
|
|
(let cmd (zero-or-more anything))
|
|
|
|
|
string-end)
|
|
|
|
|
(eat--t-set-cmd cmd))
|
|
|
|
|
;; OSC 5 1 ; e ; G ST
|
|
|
|
|
("51;e;G"
|
|
|
|
|
(eat--t-cmd-start))
|
|
|
|
|
;; OSC 5 1 ; e ; H ; <n> ST
|
|
|
|
|
((rx string-start "51;e;H;"
|
|
|
|
|
(let status (one-or-more digit))
|
|
|
|
|
string-end)
|
|
|
|
|
(eat--t-cmd-finish (string-to-number status)))
|
|
|
|
|
;; OSC 5 2 ; <t> ; <s> ST.
|
2022-09-02 20:03:33 +06:00
|
|
|
|
((rx string-start "52;"
|
|
|
|
|
(let targets
|
2023-03-28 13:58:43 +06:00
|
|
|
|
(zero-or-more (not ?\;)))
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
?\; (let data (zero-or-more anything))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
string-end)
|
|
|
|
|
(eat--t-manipulate-selection
|
|
|
|
|
targets data))))))))))
|
|
|
|
|
(`(read-charset-standard ,slot ,buf)
|
|
|
|
|
;; Find the end.
|
|
|
|
|
(let ((match (string-match (rx (any ?0 ?2 ?4 ?5 ?6 ?7 ?9 ?<
|
|
|
|
|
?= ?> ?? ?A ?B ?C ?E ?H
|
|
|
|
|
?K ?Q ?R ?Y ?Z ?f))
|
|
|
|
|
output index)))
|
|
|
|
|
(if (not match)
|
|
|
|
|
(progn
|
|
|
|
|
;; Not found, store the text to process it later when
|
|
|
|
|
;; we find the end.
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term)
|
|
|
|
|
`(read-charset-standard
|
|
|
|
|
,slot ,(concat buf (substring
|
|
|
|
|
output index))))
|
|
|
|
|
(setq index (length output)))
|
|
|
|
|
;; Got the end!
|
|
|
|
|
(let ((str (concat buf (substring output index
|
|
|
|
|
(match-end 0)))))
|
|
|
|
|
(setq index (match-end 0))
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term) nil)
|
|
|
|
|
;; Set the character set.
|
|
|
|
|
(eat--t-set-charset
|
|
|
|
|
slot
|
|
|
|
|
(pcase str
|
|
|
|
|
;; ESC ( 0.
|
|
|
|
|
;; ESC ) 0.
|
|
|
|
|
;; ESC * 0.
|
|
|
|
|
;; ESC + 0.
|
|
|
|
|
("0" 'dec-line-drawing)
|
|
|
|
|
;; ESC ( B.
|
|
|
|
|
;; ESC ) B.
|
|
|
|
|
;; ESC * B.
|
|
|
|
|
;; ESC + B.
|
|
|
|
|
("B" 'us-ascii)))))))
|
|
|
|
|
(`(read-charset-vt300 ,_slot)
|
2022-12-15 20:18:04 +06:00
|
|
|
|
(cl-incf index)
|
|
|
|
|
(setf (eat--t-term-parser-state eat--t-term) nil)
|
|
|
|
|
;; Nothing. This is here to just recognize the sequence.
|
|
|
|
|
)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--t-resize (width height)
|
|
|
|
|
"Resize terminal to WIDTH x HEIGHT."
|
|
|
|
|
(let* ((disp (eat--t-term-display eat--t-term))
|
|
|
|
|
(cursor (eat--t-disp-cursor disp))
|
|
|
|
|
(old-width (eat--t-disp-width disp))
|
|
|
|
|
(old-height (eat--t-disp-height disp)))
|
|
|
|
|
;; Don't do anything if size hasn't changed, or the new size is
|
|
|
|
|
;; too small.
|
|
|
|
|
(when (and (not (and (eq old-width width)
|
|
|
|
|
(eq old-height height)))
|
|
|
|
|
(>= width 1)
|
|
|
|
|
(>= height 1))
|
|
|
|
|
;; Update state.
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setf (eat--t-disp-width disp) width)
|
|
|
|
|
(setf (eat--t-disp-height disp) height)
|
|
|
|
|
(setf (eat--t-term-scroll-begin eat--t-term) 1)
|
|
|
|
|
(setf (eat--t-term-scroll-end eat--t-term)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat--t-disp-height disp))
|
|
|
|
|
(set-marker (eat--t-cur-position cursor) (point))
|
|
|
|
|
(if (eat--t-term-main-display eat--t-term)
|
|
|
|
|
;; For alternative display, just delete the part of the
|
|
|
|
|
;; display that went out of the edges. So if the terminal
|
|
|
|
|
;; was enlarged, we don't have anything to do.
|
|
|
|
|
(when (or (< width old-width)
|
|
|
|
|
(< height old-height))
|
|
|
|
|
;; Go to the beginning of display.
|
|
|
|
|
(goto-char (eat--t-disp-begin disp))
|
|
|
|
|
(dotimes (l height)
|
|
|
|
|
(eat--t-col-motion width)
|
|
|
|
|
(delete-region (point) (car (eat--t-eol)))
|
|
|
|
|
(if (< (1+ l) height)
|
|
|
|
|
(forward-char)
|
|
|
|
|
(delete-region (point) (point-max))
|
|
|
|
|
(let ((y (eat--t-cur-y cursor))
|
|
|
|
|
(x (eat--t-cur-x cursor)))
|
|
|
|
|
(eat--t-goto 1 1)
|
|
|
|
|
(eat--t-goto y x)))))
|
|
|
|
|
;; REVIEW: This works, but it is very simple. Most
|
|
|
|
|
;; terminals have more sophisticated mechanisms to do this.
|
|
|
|
|
;; It would be nice thing have them here.
|
|
|
|
|
;; Go to the beginning of display.
|
|
|
|
|
(goto-char (eat--t-disp-begin disp))
|
|
|
|
|
;; Try to move to the end of previous line, maybe that's a
|
|
|
|
|
;; part of a too long line.
|
|
|
|
|
(unless (bobp)
|
|
|
|
|
(backward-char))
|
|
|
|
|
;; Join all long lines.
|
|
|
|
|
(while (not (eobp))
|
|
|
|
|
(eat--t-join-long-line))
|
|
|
|
|
;; Go to display beginning again and break long lines.
|
|
|
|
|
(goto-char (eat--t-disp-begin disp))
|
|
|
|
|
(while (not (eobp))
|
|
|
|
|
(eat--t-break-long-line (eat--t-disp-width disp)))
|
|
|
|
|
;; Calculate the beginning position of display.
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
;; TODO: This part needs explanation.
|
2022-11-28 12:40:19 +06:00
|
|
|
|
(let ((disp-begin (car (eat--t-bol (- (1- height))))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when (< (eat--t-disp-begin disp) disp-begin)
|
|
|
|
|
(goto-char (max (- (eat--t-disp-begin disp) 1)
|
|
|
|
|
(point-min)))
|
|
|
|
|
(set-marker (eat--t-disp-begin disp) disp-begin)
|
|
|
|
|
(while (< (point) (1- (eat--t-disp-begin disp)))
|
|
|
|
|
(eat--t-join-long-line
|
|
|
|
|
(1- (eat--t-disp-begin disp))))))
|
|
|
|
|
;; Update the cursor if needed.
|
|
|
|
|
(when (< (eat--t-cur-position cursor)
|
|
|
|
|
(eat--t-disp-begin disp))
|
|
|
|
|
(set-marker (eat--t-cur-position cursor)
|
|
|
|
|
(eat--t-disp-begin disp)))
|
|
|
|
|
;; Update the coordinates of cursor.
|
|
|
|
|
(goto-char (eat--t-cur-position cursor))
|
|
|
|
|
(setf (eat--t-cur-x cursor) (1+ (eat--t-current-col)))
|
|
|
|
|
(goto-char (eat--t-disp-begin disp))
|
|
|
|
|
(setf (eat--t-cur-y cursor)
|
|
|
|
|
(let ((y 0))
|
|
|
|
|
(while (< (point) (eat--t-cur-position cursor))
|
|
|
|
|
(condition-case nil
|
|
|
|
|
(search-forward
|
|
|
|
|
"\n" (eat--t-cur-position cursor))
|
|
|
|
|
(search-failed
|
|
|
|
|
(goto-char (eat--t-cur-position cursor))))
|
|
|
|
|
(cl-incf y))
|
|
|
|
|
(when (or (= (point) (point-min))
|
|
|
|
|
(= (char-before) ?\n))
|
|
|
|
|
(cl-incf y))
|
|
|
|
|
(max y 1)))))))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun eat-term-make (buffer position)
|
|
|
|
|
"Make a Eat terminal at POSITION in BUFFER."
|
|
|
|
|
(eat--t-make-term
|
|
|
|
|
:buffer buffer
|
|
|
|
|
:begin (copy-marker position t)
|
|
|
|
|
:end (copy-marker position)
|
|
|
|
|
:display (eat--t-make-disp
|
|
|
|
|
:begin (copy-marker position)
|
|
|
|
|
:old-begin (copy-marker position)
|
|
|
|
|
:cursor (eat--t-make-cur
|
|
|
|
|
:position (copy-marker position)))))
|
|
|
|
|
|
|
|
|
|
(defmacro eat--t-with-env (terminal &rest body)
|
|
|
|
|
"Setup the environment for TERMINAL and eval BODY in it."
|
|
|
|
|
(declare (indent 1))
|
|
|
|
|
`(let ((eat--t-term ,terminal))
|
|
|
|
|
(with-current-buffer (eat--t-term-buffer eat--t-term)
|
|
|
|
|
(save-excursion
|
|
|
|
|
(save-restriction
|
|
|
|
|
(narrow-to-region (eat--t-term-begin eat--t-term)
|
|
|
|
|
(eat--t-term-end eat--t-term))
|
|
|
|
|
(goto-char (eat--t-cur-position
|
|
|
|
|
(eat--t-disp-cursor
|
|
|
|
|
(eat--t-term-display eat--t-term))))
|
|
|
|
|
(unwind-protect
|
|
|
|
|
(progn ,@body)
|
|
|
|
|
(set-marker (eat--t-cur-position
|
|
|
|
|
(eat--t-disp-cursor
|
|
|
|
|
(eat--t-term-display eat--t-term)))
|
|
|
|
|
(point))
|
|
|
|
|
(set-marker (eat--t-term-begin eat--t-term) (point-min))
|
|
|
|
|
(set-marker (eat--t-term-end eat--t-term)
|
|
|
|
|
(point-max))))))))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-delete (terminal)
|
|
|
|
|
"Delete TERMINAL and do any cleanup to do."
|
|
|
|
|
(let ((inhibit-quit t)
|
|
|
|
|
(eat--t-term terminal))
|
|
|
|
|
(with-current-buffer (eat--t-term-buffer eat--t-term)
|
|
|
|
|
(save-excursion
|
|
|
|
|
(save-restriction
|
|
|
|
|
(narrow-to-region (eat--t-term-begin eat--t-term)
|
|
|
|
|
(eat--t-term-end eat--t-term))
|
|
|
|
|
(eat--t-set-cursor-state :default)
|
|
|
|
|
;; Go to the beginning of display.
|
|
|
|
|
(goto-char (eat--t-disp-begin
|
|
|
|
|
(eat--t-term-display eat--t-term)))
|
|
|
|
|
;; Join all long lines.
|
|
|
|
|
(unless (bobp)
|
|
|
|
|
(backward-char))
|
|
|
|
|
(while (not (eobp))
|
|
|
|
|
(eat--t-join-long-line)))))))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-reset (terminal)
|
|
|
|
|
"Reset TERMINAL."
|
|
|
|
|
(let ((inhibit-quit t))
|
|
|
|
|
(eat--t-with-env terminal
|
|
|
|
|
(eat--t-reset))))
|
|
|
|
|
|
2022-12-10 02:14:28 +06:00
|
|
|
|
(defun eat-term-parameter (terminal parameter)
|
|
|
|
|
"Return the value of parameter PARAMETER of TERMINAL."
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(gethash parameter (eat--t-term-params terminal)))
|
2022-12-10 02:14:28 +06:00
|
|
|
|
|
|
|
|
|
(defun eat-term-set-parameter (terminal parameter value)
|
|
|
|
|
"Set the value of parameter PARAMETER of TERMINAL to VALUE."
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
;; Handle special parameters, and reject invalid values.
|
|
|
|
|
(pcase parameter
|
|
|
|
|
('bold-face
|
2022-12-17 16:11:18 +06:00
|
|
|
|
(unless (and (symbolp value) (facep value))
|
|
|
|
|
(signal 'wrong-type-argument (list '(symbolp facep) value)))
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(setf (eat--t-term-bold-face terminal) value))
|
|
|
|
|
('faint-face
|
2022-12-17 16:11:18 +06:00
|
|
|
|
(unless (and (symbolp value) (facep value))
|
|
|
|
|
(signal 'wrong-type-argument (list '(symbolp facep) value)))
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(setf (eat--t-term-faint-face terminal) value))
|
|
|
|
|
('italic-face
|
2022-12-17 16:11:18 +06:00
|
|
|
|
(unless (and (symbolp value) (facep value))
|
|
|
|
|
(signal 'wrong-type-argument (list '(symbolp facep) value)))
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(setf (eat--t-term-italic-face terminal) value))
|
|
|
|
|
('slow-blink-face
|
2022-12-17 16:11:18 +06:00
|
|
|
|
(unless (and (symbolp value) (facep value))
|
|
|
|
|
(signal 'wrong-type-argument (list '(symbolp facep) value)))
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(setf (eat--t-term-slow-blink-face terminal) value))
|
|
|
|
|
('fast-blink-face
|
2022-12-17 16:11:18 +06:00
|
|
|
|
(unless (and (symbolp value) (facep value))
|
|
|
|
|
(signal 'wrong-type-argument (list '(symbolp facep) value)))
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(setf (eat--t-term-fast-blink-face terminal) value))
|
|
|
|
|
((and (pred symbolp)
|
|
|
|
|
(let (rx string-start "color-"
|
|
|
|
|
(let number (one-or-more (any (?0 . ?9))))
|
|
|
|
|
"-face" string-end)
|
|
|
|
|
(symbol-name parameter))
|
|
|
|
|
(let (and (pred (<= 0))
|
|
|
|
|
(pred (>= 255))
|
|
|
|
|
index)
|
|
|
|
|
(string-to-number number)))
|
2022-12-17 16:11:18 +06:00
|
|
|
|
(unless (and (symbolp value) (facep value))
|
|
|
|
|
(signal 'wrong-type-argument (list '(symbolp facep) value)))
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(setf (aref (eat--t-term-color-faces terminal) index)
|
|
|
|
|
value))
|
|
|
|
|
((and (pred symbolp)
|
|
|
|
|
(let (rx string-start "font-"
|
|
|
|
|
(let number (one-or-more (any (?0 . ?9))))
|
|
|
|
|
"-face" string-end)
|
|
|
|
|
(symbol-name parameter))
|
|
|
|
|
(let (and (pred (<= 0))
|
|
|
|
|
(pred (>= 255))
|
|
|
|
|
index)
|
|
|
|
|
(string-to-number number)))
|
2022-12-17 16:11:18 +06:00
|
|
|
|
(unless (and (symbolp value) (facep value))
|
|
|
|
|
(signal 'wrong-type-argument (list '(symbolp facep) value)))
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
(setf (aref (eat--t-term-font-faces terminal) index)
|
|
|
|
|
value)))
|
|
|
|
|
;; Set the parameter.
|
|
|
|
|
(puthash parameter value (eat--t-term-params terminal)))
|
2022-12-10 02:14:28 +06:00
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-parameter (value terminal parameter)
|
|
|
|
|
`(eat-term-set-parameter ,terminal ,parameter ,value))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defun eat-term-input-function (terminal)
|
|
|
|
|
"Return the function used to send input from TERMINAL.
|
|
|
|
|
|
|
|
|
|
The function is called with two arguments, TERMINAL and the string to
|
|
|
|
|
send. The function should not change point and buffer restriction.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-input-function' TERMINAL) FUNCTION),
|
|
|
|
|
where FUNCTION is the input function."
|
|
|
|
|
(eat--t-term-input-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-input-function (function terminal)
|
|
|
|
|
`(setf (eat--t-term-input-fn ,terminal) ,function))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-cursor-type (terminal)
|
|
|
|
|
"Return the cursor state of TERMINAL.
|
|
|
|
|
|
|
|
|
|
The return value can be one of the following:
|
|
|
|
|
|
|
|
|
|
`:default' Default cursor.
|
|
|
|
|
`:invisible' Invisible cursor.
|
|
|
|
|
`:very-visible' Very visible cursor."
|
|
|
|
|
(eat--t-term-cur-state terminal))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-set-cursor-function (terminal)
|
|
|
|
|
"Return the function used to set the cursor of TERMINAL.
|
|
|
|
|
|
|
|
|
|
The function is called with two arguments, TERMINAL and a symbol STATE
|
|
|
|
|
describing the new state of cursor. The function should not change
|
|
|
|
|
point and buffer restriction. STATE can be one of the following:
|
|
|
|
|
|
|
|
|
|
`:default' Default cursor.
|
|
|
|
|
`:invisible' Invisible cursor.
|
|
|
|
|
`:very-visible' Very visible cursor. Can also be implemented
|
|
|
|
|
as blinking cursor.
|
|
|
|
|
|
|
|
|
|
More possible values might be added in future. So in case the
|
|
|
|
|
function doesn't know about a particular cursor state, it should reset
|
|
|
|
|
the cursor to the default like the `:default' state.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-set-cursor-function' TERMINAL)
|
|
|
|
|
FUNCTION), where FUNCTION is the function to set cursor."
|
|
|
|
|
(eat--t-term-set-cursor-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-set-cursor-function (function terminal)
|
|
|
|
|
`(setf (eat--t-term-set-cursor-fn ,terminal) ,function))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-grab-mouse-function (terminal)
|
|
|
|
|
"Return the function used to grab the mouse.
|
|
|
|
|
|
|
|
|
|
The function is called with two arguments, TERMINAL and a symbol MODE
|
|
|
|
|
describing the new mouse mode MODE. The function should not change
|
|
|
|
|
point and buffer restriction. MODE can be one of the following:
|
|
|
|
|
|
|
|
|
|
nil Disable mouse.
|
|
|
|
|
`:click' Pass `mouse-1', `mouse-2', and `mouse-3'
|
|
|
|
|
clicks.
|
|
|
|
|
`:modifier-click' Pass all mouse click events on both press and
|
|
|
|
|
release, including `control', `meta' and
|
|
|
|
|
`shift' modifiers.
|
|
|
|
|
`:drag' All of `:modifier-click', plus dragging
|
|
|
|
|
(moving mouse while pressed) information.
|
|
|
|
|
`:all' Pass all mouse events, including movement.
|
|
|
|
|
|
|
|
|
|
More possible values might be added in future. So in case the
|
|
|
|
|
function doesn't know about a particular mouse mode, it should behave
|
|
|
|
|
as if MODE was nil and disable mouse.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-set-mouse-mode-function' TERMINAL)
|
|
|
|
|
FUNCTION), where FUNCTION is the function to set mouse mode."
|
|
|
|
|
(eat--t-term-grab-mouse-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-grab-mouse-function (function terminal)
|
|
|
|
|
`(setf (eat--t-term-grab-mouse-fn ,terminal) ,function))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-grab-focus-events-function (terminal)
|
|
|
|
|
"Return the function used to grab focus in and out events.
|
|
|
|
|
|
|
|
|
|
The function is called with two arguments, TERMINAL and a boolean
|
|
|
|
|
describing the new grabbing mode. When the boolean is nil, don't send
|
|
|
|
|
focus event, otherwise send focus events. The function should not
|
|
|
|
|
change point and buffer restriction.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-grab-focus-events-function'
|
|
|
|
|
TERMINAL) FUNCTION), where FUNCTION is the function to grab focus
|
|
|
|
|
events."
|
|
|
|
|
(eat--t-term-set-focus-ev-mode-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-grab-focus-events-function
|
|
|
|
|
(function terminal)
|
|
|
|
|
`(setf (eat--t-term-set-focus-ev-mode-fn ,terminal) ,function))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-manipulate-selection-function (terminal)
|
|
|
|
|
"Return the function used to manipulate selection (or `kill-ring').
|
|
|
|
|
|
|
|
|
|
The function is called with three arguments, TERMINAL, a symbol
|
|
|
|
|
SELECTION describing the selection paramater and DATA, a string, or a
|
|
|
|
|
boolean. The function should not change point and buffer restriction.
|
|
|
|
|
SELECTION can be one of `:clipboard', `:primary', `:secondary',
|
|
|
|
|
`:select'. When DATA is a string, it should set the selection to that
|
|
|
|
|
string, when DATA is nil, it should unset the selection, and when DATA
|
|
|
|
|
is t, it should return the selection, or nil if none.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-manipulate-selection-function'
|
|
|
|
|
TERMINAL) FUNCTION), where FUNCTION is the function to manipulate
|
|
|
|
|
selection."
|
|
|
|
|
(eat--t-term-manipulate-selection-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-manipulate-selection-function
|
|
|
|
|
(function terminal)
|
|
|
|
|
`(setf (eat--t-term-manipulate-selection-fn ,terminal) ,function))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-ring-bell-function (terminal)
|
|
|
|
|
"Return the function used to ring the bell.
|
|
|
|
|
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
The function is called with a single argument TERMINAL. The function
|
|
|
|
|
should not change point and buffer restriction.
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-ring-bell-function' TERMINAL)
|
|
|
|
|
FUNCTION), where FUNCTION is the function to ring the bell."
|
2023-03-28 13:58:43 +06:00
|
|
|
|
(eat--t-term-bell-fn terminal))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-ring-bell-function (function terminal)
|
|
|
|
|
`(setf (eat--t-term-bell-fn ,terminal) ,function))
|
|
|
|
|
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
(defun eat-term-title (terminal)
|
|
|
|
|
"Return the current title of TERMINAL."
|
|
|
|
|
(eat--t-term-title terminal))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-set-title-function (terminal)
|
|
|
|
|
"Return the function used to set the title of TERMINAL.
|
|
|
|
|
|
|
|
|
|
The function is called with two arguments, TERMINAL and the new title
|
|
|
|
|
of TERMINAL. The function should not change point and buffer
|
|
|
|
|
restriction.
|
|
|
|
|
|
|
|
|
|
Note that the client is responsible for the arguments to the function,
|
|
|
|
|
verify them before using.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-set-title-function' TERMINAL)
|
|
|
|
|
FUNCTION), where FUNCTION is the function to set title."
|
|
|
|
|
(eat--t-term-set-title-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-set-title-function (function terminal)
|
|
|
|
|
`(setf (eat--t-term-set-title-fn ,terminal) ,function))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-cwd (terminal)
|
|
|
|
|
"Return the current working directory of TERMINAL with the hostname.
|
|
|
|
|
|
|
|
|
|
The return value is of form (HOST . PATH), where HOST is the hostname
|
|
|
|
|
and PATH is the working directory."
|
|
|
|
|
(eat--t-term-cwd terminal))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-set-cwd-function (terminal)
|
|
|
|
|
"Return the function used to set the working directory of TERMINAL.
|
|
|
|
|
|
|
|
|
|
The function is called with three arguments, TERMINAL, the host where
|
|
|
|
|
the directory is, and the new (current) working directory of TERMINAL.
|
|
|
|
|
The function should not change point and buffer restriction.
|
|
|
|
|
|
|
|
|
|
Note that the client is responsible for the arguments to the function,
|
|
|
|
|
verify them before using.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-set-cwd-function' TERMINAL)
|
|
|
|
|
FUNCTION), where FUNCTION is the function to set the current working
|
|
|
|
|
directory."
|
|
|
|
|
(eat--t-term-set-cwd-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-set-cwd-function (function terminal)
|
|
|
|
|
`(setf (eat--t-term-set-cwd-fn ,terminal) ,function))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-prompt-start-function (terminal)
|
|
|
|
|
"Return the function called just before shell prompt.
|
|
|
|
|
|
|
|
|
|
The function is called with with a single argument, TERMINAL. The
|
|
|
|
|
function should not change point and buffer restriction.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-prompt-start-function' TERMINAL)
|
|
|
|
|
FUNCTION), where FUNCTION is the function to call."
|
|
|
|
|
(eat--t-term-prompt-start-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-prompt-start-function (function terminal)
|
|
|
|
|
`(setf (eat--t-term-prompt-start-fn ,terminal) ,function))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-prompt-end-function (terminal)
|
|
|
|
|
"Return the function called just after shell prompt.
|
|
|
|
|
|
|
|
|
|
The function is called with with a single argument, TERMINAL. The
|
|
|
|
|
function should not change point and buffer restriction.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-prompt-end-function' TERMINAL)
|
|
|
|
|
FUNCTION), where FUNCTION is the function to call."
|
|
|
|
|
(eat--t-term-prompt-end-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-prompt-end-function (function terminal)
|
|
|
|
|
`(setf (eat--t-term-prompt-end-fn ,terminal) ,function))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-continuation-prompt-start-function (terminal)
|
|
|
|
|
"Return the function called just before shell continuation prompt.
|
|
|
|
|
|
|
|
|
|
The function is called with with a single argument, TERMINAL. The
|
|
|
|
|
function should not change point and buffer restriction.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-continuation-prompt-start-function'
|
|
|
|
|
TERMINAL) FUNCTION), where FUNCTION is the function to call."
|
|
|
|
|
(eat--t-term-cont-prompt-start-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-continuation-prompt-start-function
|
|
|
|
|
(function terminal)
|
|
|
|
|
`(setf (eat--t-term-cont-prompt-start-fn ,terminal) ,function))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-continuation-prompt-end-function (terminal)
|
|
|
|
|
"Return the function called just after shell continuation prompt.
|
|
|
|
|
|
|
|
|
|
The function is called with with a single argument, TERMINAL. The
|
|
|
|
|
function should not change point and buffer restriction.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-continuation-prompt-end-function'
|
|
|
|
|
TERMINAL) FUNCTION), where FUNCTION is the function to call."
|
|
|
|
|
(eat--t-term-cont-prompt-end-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-continuation-prompt-end-function
|
|
|
|
|
(function terminal)
|
|
|
|
|
`(setf (eat--t-term-cont-prompt-end-fn ,terminal) ,function))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-set-cmd-function (terminal)
|
|
|
|
|
"Return the function used to set the command being run in TERMINAL.
|
|
|
|
|
|
|
|
|
|
The function is called with two arguments, TERMINAL, the host where
|
|
|
|
|
the directory is, and the new (current) working directory of TERMINAL.
|
|
|
|
|
The function should not change point and buffer restriction.
|
|
|
|
|
|
|
|
|
|
Note that the client is responsible for the arguments to the function,
|
|
|
|
|
verify them before using.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-set-cwd-function' TERMINAL)
|
|
|
|
|
FUNCTION), where FUNCTION is the function to set the command."
|
|
|
|
|
(eat--t-term-set-cmd-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-set-cmd-function (function terminal)
|
|
|
|
|
`(setf (eat--t-term-set-cmd-fn ,terminal) ,function))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-cmd-start-function (terminal)
|
|
|
|
|
"Return the function called just before a command is run in shell.
|
|
|
|
|
|
|
|
|
|
The function is called with with a single argument, TERMINAL. The
|
|
|
|
|
function should not change point and buffer restriction.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-cmd-start-function' TERMINAL)
|
|
|
|
|
FUNCTION), where FUNCTION is the function to call."
|
|
|
|
|
(eat--t-term-cmd-start-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-cmd-start-function (function terminal)
|
|
|
|
|
`(setf (eat--t-term-cmd-start-fn ,terminal) ,function))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-cmd-finish-function (terminal)
|
|
|
|
|
"Return the function called after a command has finished in shell.
|
|
|
|
|
|
|
|
|
|
The function is called with with a two arguments, TERMINAL and the
|
|
|
|
|
exit status of the command. The function should not change point and
|
|
|
|
|
buffer restriction.
|
|
|
|
|
|
|
|
|
|
To set it, use (`setf' (`eat-term-cmd-finish-function' TERMINAL)
|
|
|
|
|
FUNCTION), where FUNCTION is the function to call."
|
|
|
|
|
(eat--t-term-cmd-finish-fn terminal))
|
|
|
|
|
|
|
|
|
|
(gv-define-setter eat-term-cmd-finish-function (function terminal)
|
|
|
|
|
`(setf (eat--t-term-cmd-finish-fn ,terminal) ,function))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defun eat-term-size (terminal)
|
|
|
|
|
"Return the size of TERMINAL as (WIDTH . HEIGHT)."
|
|
|
|
|
(let ((disp (eat--t-term-display terminal)))
|
|
|
|
|
(cons (eat--t-disp-width disp) (eat--t-disp-height disp))))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-beginning (terminal)
|
|
|
|
|
"Return the beginning position of TERMINAL.
|
|
|
|
|
|
|
|
|
|
Don't use markers to store the position, call this function whenever
|
|
|
|
|
you need the position."
|
|
|
|
|
(eat--t-term-begin terminal))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-end (terminal)
|
|
|
|
|
"Return the end position of TERMINAL.
|
|
|
|
|
|
|
|
|
|
This is also the end position of TERMINAL's display.
|
|
|
|
|
|
|
|
|
|
Don't use markers to store the position, call this function whenever
|
|
|
|
|
you need the position."
|
|
|
|
|
(eat--t-term-end terminal))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-display-beginning (terminal)
|
|
|
|
|
"Return the beginning position of TERMINAL's display."
|
|
|
|
|
(eat--t-disp-begin (eat--t-term-display terminal)))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-display-cursor (terminal)
|
|
|
|
|
"Return the cursor's current position on TERMINAL's display."
|
|
|
|
|
(let* ((disp (eat--t-term-display terminal))
|
|
|
|
|
(cursor (eat--t-disp-cursor disp)))
|
|
|
|
|
;; The cursor might be after the edge of the display. But we
|
|
|
|
|
;; don't want the UI to show that, so show cursor at the edge.
|
|
|
|
|
(if (> (eat--t-cur-x cursor) (eat--t-disp-width disp))
|
|
|
|
|
(1- (eat--t-cur-position cursor))
|
|
|
|
|
(eat--t-cur-position cursor))))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-process-output (terminal output)
|
|
|
|
|
"Process OUTPUT from client and show it on TERMINAL's display."
|
|
|
|
|
(let ((inhibit-quit t))
|
|
|
|
|
(eat--t-with-env terminal
|
|
|
|
|
(eat--t-handle-output output))))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-redisplay (terminal)
|
|
|
|
|
"Prepare TERMINAL for displaying."
|
|
|
|
|
(let ((inhibit-quit t))
|
|
|
|
|
(eat--t-with-env terminal
|
2022-11-28 12:40:19 +06:00
|
|
|
|
(let ((disp (eat--t-term-display eat--t-term)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when (< (eat--t-disp-old-begin disp)
|
|
|
|
|
(eat--t-disp-begin disp))
|
|
|
|
|
;; Join long lines.
|
|
|
|
|
(let ((limit (copy-marker (1- (eat--t-disp-begin disp)))))
|
|
|
|
|
(save-excursion
|
|
|
|
|
(goto-char (max (1- (eat--t-disp-old-begin disp))
|
|
|
|
|
(point-min)))
|
|
|
|
|
(while (< (point) limit)
|
|
|
|
|
(eat--t-join-long-line limit))))
|
|
|
|
|
;; Truncate scrollback.
|
|
|
|
|
(when eat-term-scrollback-size
|
|
|
|
|
(delete-region
|
|
|
|
|
(point-min)
|
|
|
|
|
(max (point-min) (- (point) eat-term-scrollback-size))))
|
|
|
|
|
(set-marker (eat--t-disp-old-begin disp)
|
|
|
|
|
(eat--t-disp-begin disp)))))))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-resize (terminal width height)
|
|
|
|
|
"Resize TERMINAL to WIDTH x HEIGHT."
|
|
|
|
|
(let ((inhibit-quit t))
|
|
|
|
|
(eat--t-with-env terminal
|
|
|
|
|
(eat--t-resize width height))))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-in-alternative-display-p (terminal)
|
|
|
|
|
"Return non-nil when TERMINAL is in alternative display mode."
|
|
|
|
|
(eat--t-term-main-display terminal))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-input-event (terminal n event &optional ref-pos)
|
|
|
|
|
"Send EVENT as input N times to TERMINAL.
|
|
|
|
|
|
|
|
|
|
EVENT should be a event. It can be any standard Emacs event, or a
|
|
|
|
|
event list of any of the following forms:
|
|
|
|
|
|
|
|
|
|
(eat-focus-in)
|
|
|
|
|
Terminal just gained focus.
|
|
|
|
|
|
|
|
|
|
(eat-focus-out)
|
|
|
|
|
Terminal just lost focus.
|
|
|
|
|
|
|
|
|
|
REF-POS is a mouse position list pointing to the start of terminal
|
|
|
|
|
display satisfying the predicate `posnp'. It is used to calculate the
|
|
|
|
|
position of mouse events and `eat-mouse-drag' events on terminal when
|
|
|
|
|
given.
|
|
|
|
|
|
|
|
|
|
For mouse events, events should be sent on both mouse button press and
|
|
|
|
|
release unless the mouse grabing mode is `:click', otherwise the
|
|
|
|
|
client process may get confused."
|
|
|
|
|
(let ((disp (eat--t-term-display terminal)))
|
|
|
|
|
(cl-flet ((send (str)
|
|
|
|
|
(funcall (eat--t-term-input-fn terminal)
|
|
|
|
|
terminal str)))
|
|
|
|
|
(dotimes (_ (or n 1))
|
|
|
|
|
(pcase event
|
|
|
|
|
;; Arrow key, `insert', `delete', `deletechar', `home',
|
|
|
|
|
;; `end', `prior', `next' and their modifier variants.
|
|
|
|
|
((and (or 'up 'down 'right 'left
|
|
|
|
|
'C-up 'C-down 'C-right 'C-left
|
|
|
|
|
'M-up 'M-down 'M-right 'M-left
|
|
|
|
|
'S-up 'S-down 'S-right 'S-left
|
|
|
|
|
'C-M-up 'C-M-down 'C-M-right 'C-M-left
|
|
|
|
|
'C-S-up 'C-S-down 'C-S-right 'C-S-left
|
|
|
|
|
'M-S-up 'M-S-down 'M-S-right 'M-S-left
|
|
|
|
|
'C-M-S-up 'C-M-S-down 'C-M-S-right 'C-M-S-left
|
|
|
|
|
'insert 'C-insert 'M-insert 'S-insert 'C-M-insert
|
|
|
|
|
'C-S-insert 'M-S-insert 'C-M-S-insert
|
|
|
|
|
'delete 'C-delete 'M-delete 'S-delete 'C-M-delete
|
|
|
|
|
'C-S-delete 'M-S-delete 'C-M-S-delete
|
|
|
|
|
'deletechar 'C-deletechar 'M-deletechar
|
|
|
|
|
'S-deletechar 'C-M-deletechar 'C-S-deletechar
|
|
|
|
|
'M-S-deletechar 'C-M-S-deletechar
|
|
|
|
|
'home 'C-home 'M-home 'S-home 'C-M-home 'C-S-home
|
|
|
|
|
'M-S-home 'C-M-S-home
|
|
|
|
|
'end 'C-end 'M-end 'S-end 'C-M-end 'C-S-end
|
|
|
|
|
'M-S-end 'C-M-S-end
|
|
|
|
|
'prior 'C-prior 'M-prior 'S-prior 'C-M-prior
|
|
|
|
|
'C-S-prior 'M-S-prior 'C-M-S-prior
|
|
|
|
|
'next 'C-next 'M-next 'S-next 'C-M-next 'C-S-next
|
|
|
|
|
'M-S-next 'C-M-S-next)
|
|
|
|
|
ev)
|
|
|
|
|
(send
|
|
|
|
|
(format
|
|
|
|
|
"\e%s%c"
|
|
|
|
|
(if (not (or (memq 'control (event-modifiers ev))
|
|
|
|
|
(memq 'meta (event-modifiers ev))
|
|
|
|
|
(memq 'shift (event-modifiers ev))))
|
|
|
|
|
(pcase (event-basic-type ev)
|
|
|
|
|
('insert "[2")
|
|
|
|
|
((or 'delete 'deletechar) "[3")
|
|
|
|
|
('prior "[5")
|
|
|
|
|
('next "[6")
|
|
|
|
|
(_ (if (eat--t-term-keypad-mode terminal)
|
|
|
|
|
"O"
|
|
|
|
|
"[")))
|
|
|
|
|
(format
|
|
|
|
|
"[%c;%c"
|
|
|
|
|
(pcase (event-basic-type ev)
|
|
|
|
|
('insert ?2)
|
|
|
|
|
((or 'delete 'deletechar) ?3)
|
|
|
|
|
('prior ?5)
|
|
|
|
|
('next ?6)
|
|
|
|
|
(_ ?1))
|
2022-11-28 22:29:15 +06:00
|
|
|
|
(pcase-exhaustive (event-modifiers ev)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
((and (pred (memq 'control))
|
|
|
|
|
(pred (memq 'meta))
|
|
|
|
|
(pred (memq 'shift)))
|
|
|
|
|
?8)
|
|
|
|
|
((and (pred (memq 'control))
|
|
|
|
|
(pred (memq 'meta)))
|
|
|
|
|
?7)
|
|
|
|
|
((and (pred (memq 'control))
|
|
|
|
|
(pred (memq 'shift)))
|
|
|
|
|
?6)
|
|
|
|
|
((and (pred (memq 'meta))
|
|
|
|
|
(pred (memq 'shift)))
|
|
|
|
|
?4)
|
|
|
|
|
((pred (memq 'control))
|
|
|
|
|
?5)
|
|
|
|
|
((pred (memq 'meta))
|
|
|
|
|
?3)
|
|
|
|
|
((pred (memq 'shift))
|
|
|
|
|
?2))))
|
|
|
|
|
(pcase (event-basic-type ev)
|
|
|
|
|
('up ?A)
|
|
|
|
|
('down ?B)
|
|
|
|
|
('right ?C)
|
|
|
|
|
('left ?D)
|
|
|
|
|
('home ?H)
|
|
|
|
|
('end ?F)
|
|
|
|
|
(_ ?~)))))
|
|
|
|
|
('backspace
|
|
|
|
|
(send "\C-?"))
|
|
|
|
|
('C-backspace
|
|
|
|
|
(send "\C-h"))
|
2023-03-31 11:27:12 +06:00
|
|
|
|
('M-backspace
|
|
|
|
|
(send "\e\C-?"))
|
|
|
|
|
('C-M-backspace
|
|
|
|
|
(send "\e\C-h"))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Function keys.
|
|
|
|
|
((and (pred symbolp)
|
|
|
|
|
fn-key
|
|
|
|
|
(let (rx string-start "f"
|
|
|
|
|
(let fn-num (one-or-more (any (?0 . ?9))))
|
|
|
|
|
string-end)
|
|
|
|
|
(symbol-name fn-key))
|
|
|
|
|
(let (and (pred (<= 1))
|
|
|
|
|
(pred (>= 63))
|
|
|
|
|
key)
|
|
|
|
|
(string-to-number fn-num)))
|
|
|
|
|
(send
|
|
|
|
|
(aref
|
|
|
|
|
["\eOP" "\eOQ" "\eOR" "\eOS" "\e[15~" "\e[17~" "\e[18~"
|
|
|
|
|
"\e[19~" "\e[20~" "\e[21~" "\e[23~" "\e[24~" "\e[1;2P"
|
|
|
|
|
"\e[1;2Q" "\e[1;2R" "\e[1;2S" "\e[15;2~" "\e[17;2~"
|
|
|
|
|
"\e[18;2~" "\e[19;2~" "\e[20;2~" "\e[21;2~" "\e[23;2~"
|
|
|
|
|
"\e[24;2~" "\e[1;5P" "\e[1;5Q" "\e[1;5R" "\e[1;5S"
|
|
|
|
|
"\e[15;5~" "\e[17;5~" "\e[18;5~" "\e[19;5~" "\e[20;5~"
|
|
|
|
|
"\e[21;5~" "\e[23;5~" "\e[24;5~" "\e[1;6P" "\e[1;6Q"
|
|
|
|
|
"\e[1;6R" "\e[1;6S" "\e[15;6~" "\e[17;6~" "\e[18;6~"
|
|
|
|
|
"\e[19;6~" "\e[20;6~" "\e[21;6~" "\e[23;6~" "\e[24;6~"
|
|
|
|
|
"\e[1;3P" "\e[1;3Q" "\e[1;3R" "\e[1;3S" "\e[15;3~"
|
|
|
|
|
"\e[17;3~" "\e[18;3~" "\e[19;3~" "\e[20;3~" "\e[21;3~"
|
|
|
|
|
"\e[23;3~" "\e[24;3~" "\e[1;4P" "\e[1;4Q" "\e[1;4R"]
|
|
|
|
|
(1- key))))
|
|
|
|
|
((and (or (pred numberp)
|
|
|
|
|
(pred symbolp))
|
|
|
|
|
char)
|
|
|
|
|
;; Adapted from Term source.
|
|
|
|
|
(when (symbolp char)
|
|
|
|
|
;; Convert `return' to C-m, etc.
|
|
|
|
|
(let ((tmp (get char 'event-symbol-elements)))
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(when tmp
|
|
|
|
|
(setq char (car tmp)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(and (symbolp char)
|
|
|
|
|
(setq tmp (get char 'ascii-character))
|
|
|
|
|
(setq char tmp))))
|
|
|
|
|
(when (numberp char)
|
2022-11-28 12:40:19 +06:00
|
|
|
|
(let ((base (event-basic-type char))
|
|
|
|
|
(mods (event-modifiers char)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Try to avoid event-convert-list if possible.
|
|
|
|
|
(if (and (characterp char)
|
|
|
|
|
(not (memq 'meta mods))
|
|
|
|
|
(not (and (memq 'control mods)
|
|
|
|
|
(memq 'shift mods))))
|
|
|
|
|
(send (format "%c" char))
|
|
|
|
|
(when (memq 'control mods)
|
|
|
|
|
(setq mods (delq 'shift mods)))
|
|
|
|
|
(let ((ch (pcase (event-convert-list
|
|
|
|
|
(append (remq 'meta mods)
|
|
|
|
|
(list base)))
|
2022-11-29 00:31:34 +06:00
|
|
|
|
(?\C-\s ?\C-@)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(?\C-/ ?\C-?)
|
|
|
|
|
(?\C-- ?\C-_)
|
|
|
|
|
(c c))))
|
|
|
|
|
(when (characterp ch)
|
|
|
|
|
(send (cond
|
|
|
|
|
((and (memq 'meta mods)
|
|
|
|
|
(memq ch '(?\[ ?O)))
|
|
|
|
|
"\e")
|
|
|
|
|
(t
|
|
|
|
|
(format
|
|
|
|
|
(if (memq 'meta mods) "\e%c" "%c")
|
|
|
|
|
ch))))))))))
|
|
|
|
|
;; Mouse handling.
|
|
|
|
|
((and (guard (eat--t-term-mouse-mode terminal))
|
|
|
|
|
mouse
|
|
|
|
|
(pred eventp)
|
|
|
|
|
(or (and (let mouse-type (event-basic-type mouse))
|
|
|
|
|
(let (rx string-start "mouse-"
|
|
|
|
|
(let key-num (one-or-more
|
|
|
|
|
(any (?0 . ?9))))
|
|
|
|
|
string-end)
|
|
|
|
|
(symbol-name mouse-type))
|
|
|
|
|
(let (and (pred (<= 1))
|
|
|
|
|
(pred (>= 11))
|
|
|
|
|
mouse-num)
|
|
|
|
|
(string-to-number key-num)))
|
|
|
|
|
(and (let 'wheel-up (event-basic-type mouse))
|
|
|
|
|
(let mouse-num 4))
|
|
|
|
|
(and (let 'wheel-down (event-basic-type mouse))
|
|
|
|
|
(let mouse-num 5))
|
|
|
|
|
(and (let 'wheel-right (event-basic-type mouse))
|
|
|
|
|
(let mouse-num 6))
|
|
|
|
|
(and (let 'wheel-left (event-basic-type mouse))
|
|
|
|
|
(let mouse-num 7))))
|
|
|
|
|
(let* ((modifiers (event-modifiers mouse))
|
|
|
|
|
(pos (if (memq 'drag modifiers)
|
|
|
|
|
(event-end mouse)
|
|
|
|
|
(event-start mouse)))
|
2022-11-25 13:00:56 +06:00
|
|
|
|
(x-y (if (< emacs-major-version 29)
|
|
|
|
|
(posn-col-row pos)
|
2022-11-30 22:40:11 +06:00
|
|
|
|
(with-suppressed-warnings
|
|
|
|
|
((callargs posn-col-row))
|
|
|
|
|
(posn-col-row pos 'use-window))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(x (1+ (car x-y)))
|
|
|
|
|
(y (1+ (cdr x-y)))
|
|
|
|
|
(button
|
|
|
|
|
(let ((b (aref
|
|
|
|
|
[0 1 2 64 65 66 67 128 129 130 131]
|
|
|
|
|
(1- mouse-num))))
|
|
|
|
|
(when (memq 'shift modifiers)
|
|
|
|
|
(cl-incf b 4))
|
|
|
|
|
(when (memq 'meta modifiers)
|
|
|
|
|
(cl-incf b 8))
|
|
|
|
|
(when (memq 'control modifiers)
|
|
|
|
|
(cl-incf b 16))
|
|
|
|
|
b)))
|
|
|
|
|
(when ref-pos
|
2022-11-30 22:40:11 +06:00
|
|
|
|
(let ((ref-x-y
|
|
|
|
|
(if (< emacs-major-version 29)
|
|
|
|
|
(posn-col-row ref-pos)
|
|
|
|
|
(with-suppressed-warnings
|
|
|
|
|
((callargs posn-col-row))
|
|
|
|
|
(posn-col-row ref-pos 'use-window)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(cl-decf x (car ref-x-y))
|
|
|
|
|
(cl-decf y (cdr ref-x-y))))
|
|
|
|
|
(when (and (<= 1 x (eat--t-disp-width disp))
|
|
|
|
|
(<= 1 y (eat--t-disp-height disp))
|
|
|
|
|
(or (eat--t-term-mouse-encoding terminal)
|
|
|
|
|
(and (<= x 95)
|
|
|
|
|
(<= y 95)
|
|
|
|
|
(<= button 95))))
|
|
|
|
|
(if (eq (eat--t-term-mouse-mode terminal) 'x10)
|
|
|
|
|
(when (and (< button 3)
|
|
|
|
|
(or (memq 'click modifiers)
|
|
|
|
|
(memq 'drag modifiers)))
|
|
|
|
|
(send
|
|
|
|
|
(if (eq (eat--t-term-mouse-encoding terminal)
|
|
|
|
|
'sgr)
|
|
|
|
|
(format "\e[<%i;%i;%iM" button x y)
|
|
|
|
|
(format "\e[M%c%c%c" (+ button 32) (+ x 32)
|
|
|
|
|
(+ y 32)))))
|
|
|
|
|
(cond
|
|
|
|
|
;; `down-mouse-1' and friends.
|
|
|
|
|
((memq 'down modifiers)
|
|
|
|
|
;; For `mouse-1', `mouse-2' and `mouse-3', keep
|
|
|
|
|
;; track the button's state, we'll need it when
|
|
|
|
|
;; button event mouse mode is enabled.
|
|
|
|
|
(when (< (logand button 3) 3)
|
|
|
|
|
(setf (eat--t-term-mouse-pressed terminal)
|
|
|
|
|
;; In XTerm and Kitty, mouse-1 is
|
|
|
|
|
;; prioritized over mouse-2, and mouse-2
|
|
|
|
|
;; over mouse-3. However St doesn't keep
|
|
|
|
|
;; track of multiple buttons.
|
|
|
|
|
(sort
|
|
|
|
|
(cons button (eat--t-term-mouse-pressed
|
|
|
|
|
terminal))
|
|
|
|
|
#'<)))
|
|
|
|
|
(send
|
|
|
|
|
(if (eq (eat--t-term-mouse-encoding terminal)
|
|
|
|
|
'sgr)
|
|
|
|
|
(format "\e[<%i;%i;%iM" button x y)
|
|
|
|
|
(format "\e[M%c%c%c" (+ button 32) (+ x 32)
|
|
|
|
|
(+ y 32)))))
|
|
|
|
|
;; `mouse-1', `mouse-2', `mouse-3', and their
|
|
|
|
|
;; `drag'ged variants.
|
|
|
|
|
((and (or (memq 'click modifiers)
|
|
|
|
|
(memq 'drag modifiers))
|
|
|
|
|
(<= mouse-num 3))
|
|
|
|
|
;; For `mouse-1', `mouse-2' and `mouse-3', keep
|
|
|
|
|
;; track the button's state, we'll need it when
|
|
|
|
|
;; button event mouse mode is enabled.
|
|
|
|
|
(setf (eat--t-term-mouse-pressed terminal)
|
|
|
|
|
(cl-delete-if
|
|
|
|
|
(lambda (b)
|
|
|
|
|
(= (logand b 3) (logand button 3)))
|
|
|
|
|
(eat--t-term-mouse-pressed terminal)))
|
|
|
|
|
(send
|
|
|
|
|
(if (eq (eat--t-term-mouse-encoding terminal)
|
|
|
|
|
'sgr)
|
|
|
|
|
(format "\e[<%i;%i;%im" button x y)
|
|
|
|
|
(format "\e[M%c%c%c" (+ (logior button 3) 32)
|
|
|
|
|
(+ x 32) (+ y 32)))))
|
|
|
|
|
;; Mouse wheel, `mouse-4' and friends.
|
|
|
|
|
(t
|
|
|
|
|
(send
|
|
|
|
|
(if (eq (eat--t-term-mouse-encoding terminal)
|
|
|
|
|
'sgr)
|
|
|
|
|
(format "\e[<%i;%i;%iM" button x y)
|
|
|
|
|
(format "\e[M%c%c%c" (+ button 32) (+ x 32)
|
|
|
|
|
(+ y 32))))))))))
|
|
|
|
|
;; Mouse movement tracking.
|
|
|
|
|
((and (guard (memq (eat--t-term-mouse-mode terminal)
|
|
|
|
|
'(button-event any-event)))
|
|
|
|
|
(pred mouse-movement-p)
|
|
|
|
|
movement)
|
|
|
|
|
(let* ((pos (event-start movement))
|
2022-11-25 13:00:56 +06:00
|
|
|
|
(x-y (if (< emacs-major-version 29)
|
|
|
|
|
(posn-col-row pos)
|
2022-11-30 22:40:11 +06:00
|
|
|
|
(with-suppressed-warnings
|
|
|
|
|
((callargs posn-col-row))
|
|
|
|
|
(posn-col-row pos 'use-window))))
|
2022-11-25 13:00:56 +06:00
|
|
|
|
(x (1+ (car x-y)))
|
|
|
|
|
(y (1+ (cdr x-y)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(button
|
|
|
|
|
(if (car (eat--t-term-mouse-pressed terminal))
|
|
|
|
|
(+ (car (eat--t-term-mouse-pressed terminal))
|
|
|
|
|
32)
|
|
|
|
|
35)))
|
|
|
|
|
(when ref-pos
|
2022-11-30 22:40:11 +06:00
|
|
|
|
(let ((ref-x-y
|
|
|
|
|
(if (< emacs-major-version 29)
|
|
|
|
|
(posn-col-row ref-pos)
|
|
|
|
|
(with-suppressed-warnings
|
|
|
|
|
((callargs posn-col-row))
|
|
|
|
|
(posn-col-row ref-pos 'use-window)))))
|
2022-11-25 13:00:56 +06:00
|
|
|
|
(cl-decf x (car ref-x-y))
|
|
|
|
|
(cl-decf y (cdr ref-x-y))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when (and (or (eq (eat--t-term-mouse-mode terminal)
|
|
|
|
|
'any-event)
|
|
|
|
|
(/= button 35))
|
|
|
|
|
(<= 1 x (eat--t-disp-width disp))
|
|
|
|
|
(<= 1 y (eat--t-disp-height disp))
|
|
|
|
|
(or (eat--t-term-mouse-encoding terminal)
|
|
|
|
|
(and (<= x 95)
|
|
|
|
|
(<= y 95)
|
|
|
|
|
(<= button 95))))
|
|
|
|
|
(send
|
|
|
|
|
(if (eq (eat--t-term-mouse-encoding terminal)
|
|
|
|
|
'sgr)
|
|
|
|
|
(format "\e[<%i;%i;%iM" button x y)
|
|
|
|
|
(format "\e[M%c%c%c" (+ button 32) (+ x 32)
|
|
|
|
|
(+ y 32)))))))
|
|
|
|
|
;; Focus events.
|
|
|
|
|
('(eat-focus-in)
|
|
|
|
|
(when (eat--t-term-focus-event-mode terminal)
|
|
|
|
|
(send "\e[I")))
|
|
|
|
|
('(eat-focus-out)
|
|
|
|
|
(when (eat--t-term-focus-event-mode terminal)
|
|
|
|
|
(send "\e[O"))))))))
|
|
|
|
|
|
|
|
|
|
(defun eat-send-string-as-yank (terminal args)
|
|
|
|
|
"Send ARGS to TERMINAL, honoring bracketed yank mode.
|
|
|
|
|
|
|
|
|
|
Each argument in ARGS can be either string or character."
|
|
|
|
|
(funcall (eat--t-term-input-fn terminal) terminal
|
|
|
|
|
(let ((str (mapconcat (lambda (s)
|
|
|
|
|
(if (stringp s) s (string s)))
|
|
|
|
|
args "")))
|
|
|
|
|
(if (eat--t-term-bracketed-yank terminal)
|
|
|
|
|
;; REVIEW: What if `str' itself contains these escape
|
|
|
|
|
;; sequences? St doesn't care and just wraps the
|
|
|
|
|
;; string with these magic escape sequences, while
|
|
|
|
|
;; Kitty tries to be smart.
|
|
|
|
|
(format "\e[200~%s\e[201~" str)
|
|
|
|
|
str))))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-make-keymap (input-command categories exceptions)
|
|
|
|
|
"Make a keymap binding INPUT-COMMAND to the events of CATEGORIES.
|
|
|
|
|
|
|
|
|
|
CATEGORIES is a list whose elements should be a one of the following
|
|
|
|
|
keywords:
|
|
|
|
|
|
|
|
|
|
`:ascii' All self-insertable characters, plus
|
|
|
|
|
`backspace', `insert', `delete' and
|
|
|
|
|
`deletechar' keys, with all possible
|
|
|
|
|
modifiers.
|
|
|
|
|
`:arrow' Arrow keys with all possible modifiers.
|
|
|
|
|
`:navigation' Navigation keys: home, end, prior (or page up)
|
|
|
|
|
and next (or page down) with all possible
|
|
|
|
|
modifiers.
|
|
|
|
|
`:function' Function keys (f1 - f63).
|
|
|
|
|
`:mouse-click' `mouse-1', `mouse-2' and `mouse-3'.
|
|
|
|
|
`:mouse-modifier' All mouse events except mouse movement.
|
|
|
|
|
`:mouse-movement' Mouse movement.
|
|
|
|
|
|
|
|
|
|
EXCEPTIONS is a list of key sequences to not bind. Don't use
|
|
|
|
|
\"M-...\" key sequences in EXCEPTIONS, use \"ESC ...\" instead."
|
|
|
|
|
(let ((map (make-sparse-keymap)))
|
2022-11-29 00:37:47 +06:00
|
|
|
|
(cl-flet ((bind (key)
|
|
|
|
|
(unless (member key exceptions)
|
|
|
|
|
(define-key map key input-command))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when (memq :ascii categories)
|
|
|
|
|
;; Bind ASCII and self-insertable characters except ESC and
|
|
|
|
|
;; DEL.
|
|
|
|
|
(bind [remap self-insert-command])
|
|
|
|
|
(cl-loop
|
|
|
|
|
for i from ?\C-@ to ?~
|
|
|
|
|
do (unless (= i meta-prefix-char)
|
2022-11-29 00:40:51 +06:00
|
|
|
|
(bind (vector i))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Bind `backspace', `delete', `deletechar', and all modified
|
|
|
|
|
;; variants.
|
|
|
|
|
(dolist (key '( backspace C-backspace
|
2023-03-31 11:27:12 +06:00
|
|
|
|
M-backspace C-M-backspace
|
2022-09-02 20:03:33 +06:00
|
|
|
|
insert C-insert M-insert S-insert C-M-insert
|
|
|
|
|
C-S-insert M-S-insert C-M-S-insert
|
|
|
|
|
delete C-delete M-delete S-delete C-M-delete
|
|
|
|
|
C-S-delete M-S-delete C-M-S-delete
|
|
|
|
|
deletechar C-deletechar M-deletechar
|
|
|
|
|
S-deletechar C-M-deletechar C-S-deletechar
|
|
|
|
|
M-S-deletechar C-M-S-deletechar))
|
2022-11-29 00:40:51 +06:00
|
|
|
|
(bind (vector key)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Bind these non-encodable keys. They are translated.
|
2022-11-29 00:31:34 +06:00
|
|
|
|
(dolist (key '(?\C-- ?\C-? ?\C-\s))
|
2022-11-29 00:40:51 +06:00
|
|
|
|
(bind (vector key)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Bind M-<ASCII> keys.
|
2022-11-29 00:40:51 +06:00
|
|
|
|
(unless (member (vector meta-prefix-char) exceptions)
|
|
|
|
|
(define-key map (vector meta-prefix-char)
|
|
|
|
|
(make-sparse-keymap))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(cl-loop
|
|
|
|
|
for i from ?\C-@ to ?~
|
|
|
|
|
do (unless (memq i '(?O ?\[))
|
2022-11-29 00:40:51 +06:00
|
|
|
|
(bind (vector meta-prefix-char i))))
|
|
|
|
|
(bind (vector meta-prefix-char meta-prefix-char))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when (memq :arrow categories)
|
|
|
|
|
(dolist (key '( up down right left
|
|
|
|
|
C-up C-down C-right C-left
|
|
|
|
|
M-up M-down M-right M-left
|
|
|
|
|
S-up S-down S-right S-left
|
|
|
|
|
C-M-up C-M-down C-M-right C-M-left
|
|
|
|
|
C-S-up C-S-down C-S-right C-S-left
|
|
|
|
|
M-S-up M-S-down M-S-right M-S-left
|
|
|
|
|
C-M-S-up C-M-S-down C-M-S-right C-M-S-left))
|
2022-11-29 00:40:51 +06:00
|
|
|
|
(bind (vector key))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when (memq :navigation categories)
|
|
|
|
|
(dolist (key '( home C-home M-home S-home C-M-home C-S-home
|
|
|
|
|
M-S-home C-M-S-home
|
|
|
|
|
end C-end M-end S-end C-M-end C-S-end
|
|
|
|
|
M-S-end C-M-S-end
|
|
|
|
|
prior C-prior M-prior S-prior C-M-prior
|
|
|
|
|
C-S-prior M-S-prior C-M-S-prior
|
|
|
|
|
next C-next M-next S-next C-M-next C-S-next
|
|
|
|
|
M-S-next C-M-S-next))
|
2022-11-29 00:40:51 +06:00
|
|
|
|
(bind (vector key))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when (memq :function categories)
|
|
|
|
|
(cl-loop
|
|
|
|
|
for i from 1 to 63
|
|
|
|
|
do (let ((key (intern (format "f%i" i))))
|
2022-11-29 00:40:51 +06:00
|
|
|
|
(bind (vector key)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when (memq :mouse-click categories)
|
|
|
|
|
(dolist (key '(mouse-1 mouse-2 mouse-3))
|
2022-11-29 00:40:51 +06:00
|
|
|
|
(bind (vector key))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when (memq :mouse-modifier categories)
|
|
|
|
|
(dolist (key
|
|
|
|
|
'( down-mouse-1 drag-mouse-1 down-mouse-2
|
|
|
|
|
drag-mouse-2 down-mouse-3 drag-mouse-3
|
|
|
|
|
C-down-mouse-1 C-drag-mouse-1 C-down-mouse-2
|
|
|
|
|
C-drag-mouse-2 C-down-mouse-3 C-drag-mouse-3
|
|
|
|
|
M-down-mouse-1 M-drag-mouse-1 M-down-mouse-2
|
|
|
|
|
M-drag-mouse-2 M-down-mouse-3 M-drag-mouse-3
|
|
|
|
|
S-down-mouse-1 S-drag-mouse-1 S-down-mouse-2
|
|
|
|
|
S-drag-mouse-2 S-down-mouse-3 S-drag-mouse-3
|
|
|
|
|
C-M-down-mouse-1 C-M-drag-mouse-1
|
|
|
|
|
C-M-down-mouse-2 C-M-drag-mouse-2
|
|
|
|
|
C-M-down-mouse-3 C-M-drag-mouse-3
|
|
|
|
|
C-S-down-mouse-1 C-S-drag-mouse-1
|
|
|
|
|
C-S-down-mouse-2 C-S-drag-mouse-2
|
|
|
|
|
C-S-down-mouse-3 C-S-drag-mouse-3
|
|
|
|
|
M-S-down-mouse-1 M-S-drag-mouse-1
|
|
|
|
|
M-S-down-mouse-2 M-S-drag-mouse-2
|
|
|
|
|
M-S-down-mouse-3 M-S-drag-mouse-3
|
|
|
|
|
C-M-S-down-mouse-1 C-M-S-drag-mouse-1
|
|
|
|
|
C-M-S-down-mouse-2 C-M-S-drag-mouse-2
|
|
|
|
|
C-M-S-down-mouse-3 C-M-S-drag-mouse-3 mouse-1
|
|
|
|
|
mouse-2 mouse-3 mouse-4 mouse-5 mouse-6 mouse-7
|
|
|
|
|
mouse-8 mouse-9 mouse-10 mouse-11 C-mouse-1
|
|
|
|
|
C-mouse-2 C-mouse-3 C-mouse-4 C-mouse-5
|
|
|
|
|
C-mouse-6 C-mouse-7 C-mouse-8 C-mouse-9
|
|
|
|
|
C-mouse-10 C-mouse-11 M-mouse-1 M-mouse-2
|
|
|
|
|
M-mouse-3 M-mouse-4 M-mouse-5 M-mouse-6
|
|
|
|
|
M-mouse-7 M-mouse-8 M-mouse-9 M-mouse-10
|
|
|
|
|
M-mouse-11 S-mouse-1 S-mouse-2 S-mouse-3
|
|
|
|
|
S-mouse-4 S-mouse-5 S-mouse-6 S-mouse-7
|
|
|
|
|
S-mouse-8 S-mouse-9 S-mouse-10 S-mouse-11
|
|
|
|
|
C-M-mouse-1 C-M-mouse-2 C-M-mouse-3 C-M-mouse-4
|
|
|
|
|
C-M-mouse-5 C-M-mouse-6 C-M-mouse-7 C-M-mouse-8
|
|
|
|
|
C-M-mouse-9 C-M-mouse-10 C-M-mouse-11
|
|
|
|
|
C-S-mouse-1 C-S-mouse-2 C-S-mouse-3 C-S-mouse-4
|
|
|
|
|
C-S-mouse-5 C-S-mouse-6 C-S-mouse-7 C-S-mouse-8
|
|
|
|
|
C-S-mouse-9 C-S-mouse-10 C-S-mouse-11
|
|
|
|
|
M-S-mouse-1 M-S-mouse-2 M-S-mouse-3 M-S-mouse-4
|
|
|
|
|
M-S-mouse-5 M-S-mouse-6 M-S-mouse-7 M-S-mouse-8
|
|
|
|
|
M-S-mouse-9 M-S-mouse-10 M-S-mouse-11
|
|
|
|
|
C-M-S-mouse-1 C-M-S-mouse-2 C-M-S-mouse-3
|
|
|
|
|
C-M-S-mouse-4 C-M-S-mouse-5 C-M-S-mouse-6
|
|
|
|
|
C-M-S-mouse-7 C-M-S-mouse-8 C-M-S-mouse-9
|
|
|
|
|
C-M-S-mouse-10 C-M-S-mouse-11 wheel-up
|
|
|
|
|
wheel-down wheel-right wheel-left C-wheel-up
|
|
|
|
|
C-wheel-down C-wheel-right C-wheel-left
|
|
|
|
|
M-wheel-up M-wheel-down M-wheel-right
|
|
|
|
|
M-wheel-left S-wheel-up S-wheel-down
|
|
|
|
|
S-wheel-right S-wheel-left C-M-wheel-up
|
|
|
|
|
C-M-wheel-down C-M-wheel-right C-M-wheel-left
|
|
|
|
|
C-S-wheel-up C-S-wheel-down C-S-wheel-right
|
|
|
|
|
C-S-wheel-left M-S-wheel-up M-S-wheel-down
|
|
|
|
|
M-S-wheel-right M-S-wheel-left C-M-S-wheel-up
|
|
|
|
|
C-M-S-wheel-down C-M-S-wheel-right
|
|
|
|
|
C-M-S-wheel-left))
|
2022-11-29 00:40:51 +06:00
|
|
|
|
(bind (vector key))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when (memq :mouse-movement categories)
|
|
|
|
|
(bind [mouse-movement])))
|
|
|
|
|
map))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-name ()
|
|
|
|
|
"Return the value of `TERM' environment variable for Eat."
|
|
|
|
|
(if (stringp eat-term-name)
|
|
|
|
|
eat-term-name
|
|
|
|
|
(funcall eat-term-name)))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-get-suitable-term-name (&optional display)
|
|
|
|
|
"Return the most suitable value for `TERM' for DISPLAY.
|
|
|
|
|
|
|
|
|
|
If the number of colors supported by display (as returned by
|
|
|
|
|
`display-color-cells') is more than 256, return \"eat-truecolor\", if
|
|
|
|
|
it is more than 8 but less than or equal to 256, return
|
|
|
|
|
\"eat-256color\", if is more than 1 but less than or equal to 8,
|
|
|
|
|
return \"eat-color\", otherwise return \"eat-mono\"."
|
|
|
|
|
(let ((colors (display-color-cells display)))
|
|
|
|
|
(cond ((> colors 256) "eat-truecolor")
|
|
|
|
|
((> colors 8) "eat-256color")
|
|
|
|
|
((> colors 1) "eat-color")
|
|
|
|
|
(t "eat-mono"))))
|
|
|
|
|
|
|
|
|
|
(defun eat-term-filter-string (string)
|
|
|
|
|
"Filter Eat's special text properties from STRING."
|
|
|
|
|
(with-temp-buffer
|
|
|
|
|
(insert string)
|
2022-12-15 12:41:27 +06:00
|
|
|
|
;; Join long lines.
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(while (not (eobp))
|
|
|
|
|
(eat--t-join-long-line))
|
2022-12-15 12:41:27 +06:00
|
|
|
|
;; Remove the invisible spaces used with multi-column characters.
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(while (not (eobp))
|
|
|
|
|
(let ((invisible-p (get-text-property
|
|
|
|
|
(point) 'eat--t-invisible-space))
|
|
|
|
|
(next-change (or (next-single-property-change
|
|
|
|
|
(point) 'eat--t-invisible-space)
|
|
|
|
|
(point-max))))
|
|
|
|
|
(when invisible-p
|
|
|
|
|
(delete-region (point) next-change))
|
|
|
|
|
(goto-char next-change)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(buffer-string)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;; Blink mode.
|
|
|
|
|
|
|
|
|
|
(defvar eat--slow-blink-state nil
|
|
|
|
|
"Current state of slowly blinking text, t means inverse video.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--fast-blink-state nil
|
|
|
|
|
"Current state of rapidly blinking text, t means inverse video.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--slow-blink-remap nil
|
|
|
|
|
"Face remapping cookie of slowly blinking face.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--fast-blink-remap nil
|
|
|
|
|
"Face remapping cookie of rapidly blinking face.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--slow-blink-timer nil
|
|
|
|
|
"Timer for blinking slowly blinking text.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--fast-blink-timer nil
|
|
|
|
|
"Timer for blinking rapidly blinking text.")
|
|
|
|
|
|
2022-11-29 00:48:04 +06:00
|
|
|
|
(declare-function face-remap-add-relative "face-remap"
|
|
|
|
|
(face &rest specs))
|
|
|
|
|
(declare-function face-remap-remove-relative "face-remap" (cookie))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defun eat--flip-slow-blink-state ()
|
|
|
|
|
"Flip the state of slowly blinking text."
|
|
|
|
|
(face-remap-remove-relative eat--slow-blink-remap)
|
|
|
|
|
(setq eat--slow-blink-remap
|
|
|
|
|
(face-remap-add-relative
|
|
|
|
|
'eat-slow-blink
|
Combine multiple setq/setf/setq-local into one
* eat.el (eat--t-reset, eat--t-goto, eat--t-write)
(eat--t-save-cur, eat--t-enable-alt-disp)
(eat--t-change-scroll-region, eat--t-set-sgr-params)
(eat--t-manipulate-selection, eat--t-handle-output)
(eat--t-resize, eat--flip-slow-blink-state)
(eat--flip-fast-blink-state, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-local-mode)
(eat--eshell-exec-visual, eat--trace-exec)
(eat--eshell-trace-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Combine multiple setq/setf/setq-local into one wherever
possible.
2022-11-28 21:54:55 +06:00
|
|
|
|
`(:box nil :inverse-video ,(not eat--slow-blink-state)))
|
|
|
|
|
eat--slow-blink-state (not eat--slow-blink-state)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--flip-fast-blink-state ()
|
|
|
|
|
"Flip the state of rapidly blinking text."
|
|
|
|
|
(face-remap-remove-relative eat--fast-blink-remap)
|
|
|
|
|
(setq eat--fast-blink-remap
|
|
|
|
|
(face-remap-add-relative
|
|
|
|
|
'eat-fast-blink
|
Combine multiple setq/setf/setq-local into one
* eat.el (eat--t-reset, eat--t-goto, eat--t-write)
(eat--t-save-cur, eat--t-enable-alt-disp)
(eat--t-change-scroll-region, eat--t-set-sgr-params)
(eat--t-manipulate-selection, eat--t-handle-output)
(eat--t-resize, eat--flip-slow-blink-state)
(eat--flip-fast-blink-state, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-local-mode)
(eat--eshell-exec-visual, eat--trace-exec)
(eat--eshell-trace-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Combine multiple setq/setf/setq-local into one wherever
possible.
2022-11-28 21:54:55 +06:00
|
|
|
|
`(:box nil :inverse-video ,(not eat--fast-blink-state)))
|
|
|
|
|
eat--fast-blink-state (not eat--fast-blink-state)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--blink-stop-timers ()
|
|
|
|
|
"Start blinking timers."
|
|
|
|
|
(when eat--slow-blink-timer
|
|
|
|
|
(cancel-timer eat--slow-blink-timer)
|
|
|
|
|
(setq eat--slow-blink-timer nil))
|
|
|
|
|
(when eat--fast-blink-timer
|
|
|
|
|
(cancel-timer eat--fast-blink-timer)
|
|
|
|
|
(setq eat--fast-blink-timer nil)))
|
|
|
|
|
|
|
|
|
|
(defun eat--blink-start-timers ()
|
|
|
|
|
"Start blinking timers."
|
|
|
|
|
(eat--blink-stop-timers)
|
|
|
|
|
(setq eat--slow-blink-timer
|
|
|
|
|
(run-with-timer t (/ (float eat-slow-blink-frequency))
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
#'eat--flip-slow-blink-state))
|
|
|
|
|
(setq eat--fast-blink-timer
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(run-with-timer t (/ (float eat-fast-blink-frequency))
|
|
|
|
|
#'eat--flip-fast-blink-state)))
|
|
|
|
|
|
|
|
|
|
(define-minor-mode eat-blink-mode
|
|
|
|
|
"Toggle blinking of text with blink attribute."
|
|
|
|
|
:lighter " Eat-Blink"
|
2022-11-29 00:58:09 +06:00
|
|
|
|
(let ((locals '( eat--slow-blink-state eat--fast-blink-state
|
|
|
|
|
eat--slow-blink-remap eat--fast-blink-remap
|
|
|
|
|
eat--slow-blink-timer eat--fast-blink-timer)))
|
|
|
|
|
(cond
|
|
|
|
|
(eat-blink-mode
|
|
|
|
|
(setq eat-blink-mode nil)
|
|
|
|
|
(require 'face-remap)
|
|
|
|
|
(setq eat-blink-mode t)
|
|
|
|
|
(mapc #'make-local-variable locals)
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setq eat--slow-blink-state nil)
|
|
|
|
|
(setq eat--fast-blink-state nil)
|
|
|
|
|
(setq eat--slow-blink-remap
|
|
|
|
|
(face-remap-add-relative 'eat-term-slow-blink
|
|
|
|
|
'(:box nil)))
|
|
|
|
|
(setq eat--fast-blink-remap
|
2022-11-29 00:58:09 +06:00
|
|
|
|
(face-remap-add-relative 'eat-term-fast-blink
|
|
|
|
|
'(:box nil)))
|
|
|
|
|
(add-hook 'pre-command-hook #'eat--blink-stop-timers nil t)
|
|
|
|
|
(add-hook 'post-command-hook #'eat--blink-start-timers nil t))
|
|
|
|
|
(t
|
|
|
|
|
(eat--blink-stop-timers)
|
|
|
|
|
(face-remap-remove-relative eat--slow-blink-remap)
|
|
|
|
|
(face-remap-remove-relative eat--fast-blink-remap)
|
|
|
|
|
(remove-hook 'pre-command-hook #'eat--blink-stop-timers t)
|
|
|
|
|
(remove-hook 'post-command-hook #'eat--blink-start-timers t)
|
|
|
|
|
(mapc #'kill-local-variable locals)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;; Buffer-local Cursor Blinking.
|
|
|
|
|
|
|
|
|
|
(defvar eat--cursor-blink-type nil
|
|
|
|
|
"Type of blinking cursor.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--cursor-blink-state nil
|
|
|
|
|
"Current state of slowly blinking text, non-nil means on.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--cursor-blink-timer nil
|
|
|
|
|
"Timer for blinking slowly blinking text.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--cursor-blink-mode)
|
|
|
|
|
|
|
|
|
|
(defun eat--flip-cursor-blink-state ()
|
|
|
|
|
"Flip the state of slowly blinking text."
|
|
|
|
|
(when (and eat--cursor-blink-mode
|
|
|
|
|
(display-graphic-p))
|
|
|
|
|
(setq-local cursor-type (if eat--cursor-blink-state
|
|
|
|
|
(caddr eat--cursor-blink-type)
|
|
|
|
|
(car eat--cursor-blink-type)))
|
|
|
|
|
(setq eat--cursor-blink-state (not eat--cursor-blink-state))
|
|
|
|
|
;; REVIEW: This is expensive, and some causes flickering. Any
|
|
|
|
|
;; better way?
|
2022-11-28 23:22:52 +06:00
|
|
|
|
(when-let* ((window (get-buffer-window nil 'visible)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(redraw-frame (window-frame window)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--cursor-blink-stop-timers ()
|
|
|
|
|
"Stop blinking timers."
|
|
|
|
|
(unless eat--cursor-blink-state
|
|
|
|
|
(eat--flip-cursor-blink-state))
|
|
|
|
|
(when eat--cursor-blink-timer
|
|
|
|
|
(cancel-timer eat--cursor-blink-timer)
|
|
|
|
|
(setq eat--cursor-blink-timer nil)))
|
|
|
|
|
|
|
|
|
|
(defun eat--cursor-blink-start-timers ()
|
|
|
|
|
"Start blinking timers."
|
|
|
|
|
(eat--cursor-blink-stop-timers)
|
|
|
|
|
(setq eat--cursor-blink-timer
|
|
|
|
|
(run-with-timer t (/ (float (cadr eat--cursor-blink-type)))
|
|
|
|
|
#'eat--flip-cursor-blink-state)))
|
|
|
|
|
|
|
|
|
|
(define-minor-mode eat--cursor-blink-mode
|
|
|
|
|
"Toggle blinking of cursor."
|
|
|
|
|
:interactive nil
|
2022-11-29 00:58:09 +06:00
|
|
|
|
(let ((locals '(eat--cursor-blink-state eat--cursor-blink-timer)))
|
|
|
|
|
(cond
|
|
|
|
|
(eat--cursor-blink-mode
|
|
|
|
|
(mapc #'make-local-variable locals)
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setq eat--cursor-blink-state nil)
|
|
|
|
|
(setq eat--cursor-blink-timer nil)
|
2022-11-29 00:58:09 +06:00
|
|
|
|
(add-hook 'pre-command-hook #'eat--cursor-blink-stop-timers nil
|
|
|
|
|
t)
|
|
|
|
|
(add-hook 'post-command-hook #'eat--cursor-blink-start-timers
|
|
|
|
|
nil t)
|
|
|
|
|
(when (current-idle-time)
|
|
|
|
|
(eat--cursor-blink-start-timers)))
|
|
|
|
|
(t
|
|
|
|
|
(eat--cursor-blink-stop-timers)
|
|
|
|
|
(remove-hook 'pre-command-hook #'eat--cursor-blink-stop-timers
|
|
|
|
|
t)
|
|
|
|
|
(remove-hook 'post-command-hook #'eat--cursor-blink-start-timers
|
|
|
|
|
t)
|
|
|
|
|
(mapc #'kill-local-variable locals)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;; User Interface.
|
|
|
|
|
|
|
|
|
|
(defvar eat--terminal nil
|
|
|
|
|
"The terminal object.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--synchronize-scroll-function nil
|
|
|
|
|
"Function to synchronize scrolling between terminal and window.")
|
|
|
|
|
|
2022-12-06 21:30:01 +06:00
|
|
|
|
(defvar eat--shell-command-status 0
|
|
|
|
|
"If the current shell command has finished, its exit status.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--shell-prompt-begin nil
|
|
|
|
|
"Beginning of last shell prompt.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--shell-prompt-mark nil
|
|
|
|
|
"Display property used to put a mark before the previous prompt.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--shell-prompt-mark-overlays nil
|
|
|
|
|
"List of overlay used to put marks before shell prompts.")
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defun eat-reset ()
|
|
|
|
|
"Perform a terminal reset."
|
|
|
|
|
(interactive)
|
|
|
|
|
(when eat--terminal
|
|
|
|
|
(let ((inhibit-read-only t))
|
|
|
|
|
(eat-term-reset eat--terminal)
|
|
|
|
|
(eat-term-redisplay eat--terminal))))
|
|
|
|
|
|
|
|
|
|
(defun eat--set-cursor (_ state)
|
|
|
|
|
"Set cursor type according to STATE.
|
|
|
|
|
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
STATE can be one of the following:
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
`:default' Default cursor.
|
|
|
|
|
`:invisible' Invisible cursor.
|
|
|
|
|
`:very-visible' Very visible cursor. Can also be implemented as
|
|
|
|
|
blinking cursor.
|
|
|
|
|
Any other value Default cursor."
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(setq-local eat--cursor-blink-type
|
|
|
|
|
(pcase state
|
|
|
|
|
(:invisible eat-invisible-cursor-type)
|
|
|
|
|
(:very-visible eat-very-visible-cursor-type)
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(_ eat-default-cursor-type))) ; `:default'
|
|
|
|
|
(setq-local cursor-type (car eat--cursor-blink-type))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat--cursor-blink-mode (if (cadr eat--cursor-blink-type) +1 -1)))
|
|
|
|
|
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
(defun eat--manipulate-kill-ring (_ selection data)
|
|
|
|
|
"Manipulate `kill-ring'.
|
|
|
|
|
|
|
|
|
|
SELECTION can be one of `:clipboard', `:primary', `:secondary',
|
|
|
|
|
`:select'. When DATA is a string, set the selection to that string,
|
|
|
|
|
when DATA is nil, unset the selection, and when DATA is t, return the
|
|
|
|
|
selection, or nil if none."
|
|
|
|
|
(let ((inhibit-eol-conversion t)
|
|
|
|
|
(select-enable-clipboard (eq selection :clipboard))
|
|
|
|
|
(select-enable-primary (eq selection :primary)))
|
|
|
|
|
(pcase-exhaustive data
|
|
|
|
|
('t
|
|
|
|
|
(when eat-enable-yank-to-terminal
|
|
|
|
|
(ignore-error error
|
|
|
|
|
(current-kill 0 'do-not-move))))
|
2023-03-28 13:58:43 +06:00
|
|
|
|
('nil
|
|
|
|
|
(when eat-enable-kill-from-terminal
|
|
|
|
|
(kill-new "")))
|
Tighter shell integration
* eat.el (eat--t-term): New slots: 'prompt-start-fn',
'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
* eat.el (eat--t-set-cwd): Accept three arguments in two
different formats.
* eat.el (eat--t-prompt-start, eat--t-prompt-end)
(eat--t-cont-prompt-start, eat--t-cont-prompt-end)
(eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
function.
* eat.el (eat--t-handle-output): Accept Eat's own
OSC 51 ; e ; ... ST sequences.
* eat.el (eat-term-prompt-start-function)
(eat-term-prompt-end-function)
(eat-term-continuation-prompt-start-function)
(eat-term-continuation-prompt-end-function)
(eat-term-set-cmd-function, eat-term-cmd-start-function)
(eat-term-cmd-finish-function): New generalized variable.
* integration/bash (__eat_current_command, __eat_exit_status):
New variable.
* integration/bash (__eat_prompt_command): Send exit status of
last command, if applicable. Use Eat specific sequence to
report working directory. Set title.
* integration/bash (__eat_preexec): Report current command and
execution start.
* integration/bash (__eat_before_prompt_command): Set
'__eat_exit_status' to the exit status of the last command.
* integration/bash (__eat_prompt_start, __eat_prompt_end)
(__eat_continuation_start, __eat_continuation_end): New
variable, used as constant only to make the code more readable.
* integration/bash (__eat_enable_integration): Wrap 'PS1' and
'PS2'. Don't set title from 'PS1'.
2022-12-05 23:50:10 +06:00
|
|
|
|
((and (pred stringp) str)
|
|
|
|
|
(when eat-enable-kill-from-terminal
|
|
|
|
|
(kill-new str))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--bell (_)
|
|
|
|
|
"Ring the bell."
|
|
|
|
|
(ding t))
|
|
|
|
|
|
|
|
|
|
(defun eat--set-cwd (_ host cwd)
|
|
|
|
|
"Set CWD as the current working directory (`default-directory').
|
|
|
|
|
|
|
|
|
|
If HOST isn't the host Emacs is running on, don't do anything."
|
|
|
|
|
(when (and eat-enable-directory-tracking
|
|
|
|
|
(string= host (system-name)))
|
|
|
|
|
(ignore-errors
|
|
|
|
|
(cd-absolute cwd))))
|
2022-12-06 12:23:28 +06:00
|
|
|
|
|
2022-12-06 21:30:01 +06:00
|
|
|
|
(defun eat--pre-prompt (_)
|
|
|
|
|
"Save the beginning position of shell prompt."
|
2023-02-07 17:13:10 +06:00
|
|
|
|
(setq eat--shell-prompt-begin (point-marker))
|
|
|
|
|
;; FIXME: It's a crime to touch processes in this section.
|
|
|
|
|
(when (eq eat-query-before-killing-running-terminal 'auto)
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(set-process-query-on-exit-flag
|
|
|
|
|
(eat-term-parameter eat--terminal 'eat--process) nil)))
|
2022-12-06 21:30:01 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--post-prompt (_)
|
|
|
|
|
"Put a mark in the marginal area on current line."
|
|
|
|
|
(when eat-enable-shell-prompt-annotation
|
|
|
|
|
(let ((indicator
|
|
|
|
|
(if (zerop eat--shell-command-status)
|
|
|
|
|
(propertize
|
|
|
|
|
eat-shell-prompt-annotation-success-margin-indicator
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
'face '(eat-shell-prompt-annotation-success default))
|
2022-12-06 21:30:01 +06:00
|
|
|
|
(propertize
|
|
|
|
|
eat-shell-prompt-annotation-failure-margin-indicator
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
'face '(eat-shell-prompt-annotation-failure default)))))
|
2022-12-06 21:30:01 +06:00
|
|
|
|
;; Update previous prompt's indicator using side-effect.
|
|
|
|
|
(when eat--shell-prompt-mark
|
|
|
|
|
(setf (cadr eat--shell-prompt-mark) indicator)
|
|
|
|
|
(setq eat--shell-prompt-mark nil))
|
|
|
|
|
;; Show this prompt's indicator.
|
|
|
|
|
(when eat--shell-prompt-begin
|
|
|
|
|
(when (< eat--shell-prompt-begin (point))
|
|
|
|
|
;; Save it, we'll use side-effect.
|
|
|
|
|
(setq eat--shell-prompt-mark
|
|
|
|
|
`((margin ,eat-shell-prompt-annotation-position)
|
|
|
|
|
,indicator))
|
|
|
|
|
;; Make overlay and put bookkeeping properties.
|
|
|
|
|
(let ((identifier (gensym "eat--prompt-mark-identifier-"))
|
|
|
|
|
(before-str
|
|
|
|
|
(propertize " " 'display eat--shell-prompt-mark))
|
|
|
|
|
(ov (make-overlay eat--shell-prompt-begin
|
|
|
|
|
(1+ eat--shell-prompt-begin))))
|
|
|
|
|
(overlay-put ov 'before-string before-str)
|
|
|
|
|
(overlay-put ov 'eat--shell-prompt-mark-id identifier)
|
|
|
|
|
(add-text-properties
|
|
|
|
|
eat--shell-prompt-begin (1+ eat--shell-prompt-begin)
|
|
|
|
|
(list 'eat--before-string before-str
|
|
|
|
|
'eat--shell-prompt-mark-id identifier
|
|
|
|
|
'eat--shell-prompt-mark-overlay ov))
|
2022-12-12 14:13:36 +06:00
|
|
|
|
(push ov eat--shell-prompt-mark-overlays))))))
|
2022-12-06 22:57:47 +06:00
|
|
|
|
(when eat--shell-prompt-begin
|
|
|
|
|
(when (< eat--shell-prompt-begin (point))
|
|
|
|
|
;; Put a text property to allow previous or next prompts.
|
|
|
|
|
(put-text-property (1- (point)) (point)
|
2022-12-12 14:13:36 +06:00
|
|
|
|
'eat--shell-prompt-end t)))
|
|
|
|
|
(setq eat--shell-prompt-begin nil))
|
2022-12-06 21:30:01 +06:00
|
|
|
|
|
2022-12-07 11:06:44 +06:00
|
|
|
|
(defun eat--correct-shell-prompt-mark-overlays (buffer)
|
|
|
|
|
"Correct all overlays used to add mark before shell prompt.
|
2022-12-06 21:30:01 +06:00
|
|
|
|
|
|
|
|
|
BUFFER is the terminal buffer."
|
|
|
|
|
(when (and (buffer-live-p buffer)
|
2022-12-08 15:58:20 +06:00
|
|
|
|
(buffer-local-value 'eat--terminal buffer)
|
2022-12-06 21:30:01 +06:00
|
|
|
|
eat-enable-shell-prompt-annotation)
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(while-no-input
|
|
|
|
|
;; Delete all outdated overlays.
|
|
|
|
|
(dolist (ov eat--shell-prompt-mark-overlays)
|
|
|
|
|
(unless (eq (overlay-get ov 'eat--shell-prompt-mark-id)
|
|
|
|
|
(get-text-property (overlay-start ov)
|
|
|
|
|
'eat--shell-prompt-mark-id))
|
|
|
|
|
(delete-overlay ov)
|
|
|
|
|
(setq eat--shell-prompt-mark-overlays
|
|
|
|
|
(delq ov eat--shell-prompt-mark-overlays))))
|
|
|
|
|
(save-excursion
|
|
|
|
|
;; Recreate overlays if needed.
|
|
|
|
|
(goto-char (eat-term-beginning eat--terminal))
|
|
|
|
|
(while (< (point) (eat-term-end eat--terminal))
|
|
|
|
|
(when (get-text-property
|
|
|
|
|
(point) 'eat--shell-prompt-mark-id)
|
|
|
|
|
(let ((ov (get-text-property
|
|
|
|
|
(point) 'eat--shell-prompt-mark-overlay)))
|
|
|
|
|
(unless
|
|
|
|
|
(and ov
|
|
|
|
|
(overlay-buffer ov)
|
|
|
|
|
(eq (overlay-get
|
|
|
|
|
ov 'eat--shell-prompt-mark-id)
|
|
|
|
|
(get-text-property
|
|
|
|
|
(point) 'eat--shell-prompt-mark-id)))
|
|
|
|
|
;; Recreate.
|
|
|
|
|
(when ov
|
|
|
|
|
(delete-overlay ov)
|
|
|
|
|
(setq eat--shell-prompt-mark-overlays
|
|
|
|
|
(delq ov eat--shell-prompt-mark-overlays)))
|
|
|
|
|
(setq ov (make-overlay (point) (1+ (point))))
|
|
|
|
|
(overlay-put ov 'before-string
|
|
|
|
|
(get-text-property
|
|
|
|
|
(point) 'eat--before-string))
|
|
|
|
|
(overlay-put ov 'eat--shell-prompt-mark-id
|
|
|
|
|
(get-text-property
|
|
|
|
|
(point) 'eat--shell-prompt-mark-id))
|
|
|
|
|
(push ov eat--shell-prompt-mark-overlays))))
|
|
|
|
|
(goto-char (or (next-single-property-change
|
|
|
|
|
(point) 'eat--shell-prompt-mark-id nil
|
|
|
|
|
(eat-term-end eat--terminal))
|
|
|
|
|
(eat-term-end eat--terminal)))))))))
|
|
|
|
|
|
2022-12-06 12:23:28 +06:00
|
|
|
|
(defun eat--set-cmd (_ cmd)
|
|
|
|
|
"Add CMD to `shell-command-history'."
|
|
|
|
|
(when eat-enable-shell-command-history
|
|
|
|
|
(add-to-history 'shell-command-history cmd)))
|
|
|
|
|
|
2022-12-06 21:30:01 +06:00
|
|
|
|
(defun eat--pre-cmd (_)
|
|
|
|
|
"Update shell prompt mark to indicate command is running."
|
2023-02-07 17:13:10 +06:00
|
|
|
|
;; FIXME: It's a crime to touch processes in this section.
|
|
|
|
|
(when (eq eat-query-before-killing-running-terminal 'auto)
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(set-process-query-on-exit-flag
|
|
|
|
|
(eat-term-parameter eat--terminal 'eat--process) t))
|
2022-12-06 21:30:01 +06:00
|
|
|
|
(when (and eat-enable-shell-prompt-annotation
|
|
|
|
|
eat--shell-prompt-mark)
|
|
|
|
|
(setf (cadr eat--shell-prompt-mark)
|
|
|
|
|
(propertize
|
|
|
|
|
eat-shell-prompt-annotation-running-margin-indicator
|
Allow changing terminal faces terminal-locally
* eat.el (eat--t-term): New slots: bold-face, faint-face,
italic-face, slow-blink-face, fast-blink-face, color-0-face,
color-faces, font-faces. Use hash table for 'params' slot.
* eat.el (eat--t-set-sgr-params): Use new slot instead using
the faces directly.
* eat.el (eat-term-parameter): Update to work with 'params'
hash table.
* eat.el (eat-term-set-parameter): Update to work with 'params'
hash table. Handle the following parameters specially:
bold-face, faint-face, italic-face, slow-blink-face,
fast-blink-face, color-0-face, color-1-face, ...,
color-255-face, font-0-face, font-1-face, ..., font-9-face.
2022-12-16 23:21:50 +06:00
|
|
|
|
'face '(eat-shell-prompt-annotation-running default)))))
|
2022-12-06 21:30:01 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--set-cmd-status (_ code)
|
|
|
|
|
"Set CODE as the current shell command's exit status."
|
|
|
|
|
(when eat-enable-shell-prompt-annotation
|
|
|
|
|
;; We'll update the mark later when the prompt appears.
|
|
|
|
|
(setq eat--shell-command-status code)))
|
|
|
|
|
|
2022-12-06 22:03:33 +06:00
|
|
|
|
(defun eat-previous-shell-prompt (&optional arg)
|
|
|
|
|
"Go to the previous shell prompt.
|
|
|
|
|
|
|
|
|
|
When numeric prefix argument, ARG, is given, go to ARGth previous
|
|
|
|
|
shell prompt."
|
|
|
|
|
(interactive "p")
|
|
|
|
|
(dotimes (_ (or arg 1))
|
|
|
|
|
(let ((previous (previous-single-property-change
|
|
|
|
|
(point) 'eat--shell-prompt-end)))
|
|
|
|
|
(goto-char (or previous (point-min)))
|
|
|
|
|
(when (get-text-property (point) 'eat--shell-prompt-end)
|
|
|
|
|
(setq previous (previous-single-property-change
|
|
|
|
|
(point) 'eat--shell-prompt-end))
|
|
|
|
|
(goto-char (or previous (point-min))))
|
|
|
|
|
(unless previous
|
|
|
|
|
(user-error "No previous prompt")))))
|
|
|
|
|
|
|
|
|
|
(defun eat-next-shell-prompt (&optional arg)
|
|
|
|
|
"Go to the next shell prompt.
|
|
|
|
|
|
|
|
|
|
When numeric prefix argument, ARG, is given, go to ARGth next shell
|
|
|
|
|
prompt."
|
|
|
|
|
(interactive "p")
|
|
|
|
|
(dotimes (_ (or arg 1))
|
|
|
|
|
(let ((next (next-single-property-change
|
|
|
|
|
(point) 'eat--shell-prompt-end)))
|
|
|
|
|
(goto-char (or next (point-max)))
|
|
|
|
|
(when (get-text-property (point) 'eat--shell-prompt-end)
|
|
|
|
|
(goto-char (or (next-single-property-change
|
|
|
|
|
(point) 'eat--shell-prompt-end)
|
|
|
|
|
(point-max))))
|
|
|
|
|
(unless next
|
|
|
|
|
(user-error "No next prompt")))))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
;;;;; Input.
|
|
|
|
|
|
|
|
|
|
(defvar eat--mouse-grabbing-type nil
|
|
|
|
|
"Current mouse grabbing type/mode.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--mouse-pressed-buttons nil
|
|
|
|
|
"Mouse buttons currently pressed.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--mouse-last-position nil
|
|
|
|
|
"Last position of mouse, nil when not dragging.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--mouse-drag-transient-map-exit nil
|
|
|
|
|
"Function to exit mouse dragging transient map.")
|
|
|
|
|
|
|
|
|
|
(defun eat-self-input (n &optional e)
|
|
|
|
|
"Send E as input N times.
|
|
|
|
|
|
|
|
|
|
N defaults to 1 and E defaults to `last-command-event' and should be a
|
|
|
|
|
event."
|
|
|
|
|
(interactive
|
|
|
|
|
(list (prefix-numeric-value current-prefix-arg)
|
|
|
|
|
(if (and (> (length (this-command-keys)) 1)
|
|
|
|
|
(eq (aref (this-command-keys)
|
|
|
|
|
(- (length (this-command-keys)) 2))
|
|
|
|
|
meta-prefix-char))
|
|
|
|
|
;; HACK: Capture meta modifier (ESC prefix) in terminal.
|
|
|
|
|
(cond
|
|
|
|
|
((eq last-command-event meta-prefix-char)
|
|
|
|
|
last-command-event)
|
|
|
|
|
((characterp last-command-event)
|
|
|
|
|
(aref
|
|
|
|
|
(kbd (format "M-%c" last-command-event))
|
|
|
|
|
0))
|
|
|
|
|
((symbolp last-command-event)
|
|
|
|
|
(aref
|
|
|
|
|
(kbd (format "M-<%S>" last-command-event))
|
|
|
|
|
0))
|
|
|
|
|
(t
|
|
|
|
|
last-command-event))
|
|
|
|
|
last-command-event)))
|
|
|
|
|
(when (memq (event-basic-type e)
|
|
|
|
|
'( mouse-1 mouse-2 mouse-3 mouse-4 mouse-5 mouse-6
|
|
|
|
|
mouse-7 mouse-8 mouse-9 mouse-10 mouse-11))
|
|
|
|
|
(select-window (posn-window (event-start e))))
|
|
|
|
|
(when eat--terminal
|
|
|
|
|
(unless (mouse-movement-p e)
|
2022-12-12 14:00:57 +06:00
|
|
|
|
(funcall eat--synchronize-scroll-function
|
|
|
|
|
(eat--synchronize-scroll-windows 'force-selected)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(if (memq (event-basic-type e)
|
|
|
|
|
'( mouse-1 mouse-2 mouse-3 mouse-4 mouse-5 mouse-6
|
|
|
|
|
mouse-7 mouse-8 mouse-9 mouse-10 mouse-11
|
|
|
|
|
mouse-movement))
|
|
|
|
|
(let ((disp-begin-posn
|
|
|
|
|
(posn-at-point
|
|
|
|
|
(eat-term-display-beginning eat--terminal)))
|
|
|
|
|
(e (if (or (not eat--mouse-last-position)
|
|
|
|
|
(eq (posn-window
|
|
|
|
|
(if (memq 'drag (event-modifiers e))
|
|
|
|
|
(event-end e)
|
|
|
|
|
(event-start e)))
|
|
|
|
|
(posn-window eat--mouse-last-position)))
|
|
|
|
|
e
|
|
|
|
|
(pcase e
|
|
|
|
|
(`(,type ,_)
|
|
|
|
|
`(,type ,eat--mouse-last-position))
|
|
|
|
|
(`(,type ,start ,_)
|
|
|
|
|
`(,type ,start ,eat--mouse-last-position))
|
|
|
|
|
(ev ev)))))
|
|
|
|
|
(if (not (mouse-movement-p e))
|
|
|
|
|
(eat-term-input-event eat--terminal n e disp-begin-posn)
|
|
|
|
|
(if (not eat--mouse-pressed-buttons)
|
|
|
|
|
(when (eq eat--mouse-grabbing-type :all)
|
|
|
|
|
(eat-term-input-event eat--terminal n e
|
|
|
|
|
disp-begin-posn))
|
|
|
|
|
(when (memq eat--mouse-grabbing-type '(:all :drag))
|
|
|
|
|
(eat-term-input-event eat--terminal n e
|
|
|
|
|
disp-begin-posn))
|
|
|
|
|
(setq eat--mouse-last-position (event-start e))))
|
|
|
|
|
(when (memq (event-basic-type e) '(mouse-1 mouse-2 mouse-3))
|
|
|
|
|
(when (or (memq 'click (event-modifiers e))
|
|
|
|
|
(memq 'drag (event-modifiers e)))
|
|
|
|
|
(setq eat--mouse-pressed-buttons
|
|
|
|
|
(delq (event-basic-type e)
|
|
|
|
|
eat--mouse-pressed-buttons))
|
|
|
|
|
(unless eat--mouse-pressed-buttons
|
|
|
|
|
(setq eat--mouse-last-position nil)
|
|
|
|
|
(when eat--mouse-drag-transient-map-exit
|
|
|
|
|
(funcall eat--mouse-drag-transient-map-exit)
|
|
|
|
|
(setq eat--mouse-drag-transient-map-exit nil))))
|
|
|
|
|
(when (memq 'down (event-modifiers e))
|
|
|
|
|
(push (event-basic-type e) eat--mouse-pressed-buttons)
|
|
|
|
|
(setq eat--mouse-last-position (event-start e))
|
|
|
|
|
(unless eat--mouse-drag-transient-map-exit
|
|
|
|
|
(let ((old-track-mouse track-mouse)
|
|
|
|
|
(buffer (current-buffer)))
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setq track-mouse 'dragging)
|
|
|
|
|
(setq eat--mouse-drag-transient-map-exit
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(set-transient-map
|
|
|
|
|
(let ((map (eat-term-make-keymap
|
|
|
|
|
#'eat-self-input
|
|
|
|
|
'(:mouse-modifier
|
|
|
|
|
:mouse-movement)
|
|
|
|
|
nil)))
|
|
|
|
|
;; Some of the events will of course end up
|
|
|
|
|
;; looked up with a mode-line, header-line
|
|
|
|
|
;; or vertical-line prefix ...
|
|
|
|
|
(define-key map [mode-line] map)
|
|
|
|
|
(define-key map [header-line] map)
|
|
|
|
|
(define-key map [tab-line] map)
|
|
|
|
|
(define-key map [vertical-line] map)
|
|
|
|
|
;; ... and some maybe even with a right- or
|
|
|
|
|
;; bottom-divider prefix.
|
|
|
|
|
(define-key map [right-divider] map)
|
|
|
|
|
(define-key map [bottom-divider] map))
|
|
|
|
|
#'always
|
|
|
|
|
(lambda ()
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(setq track-mouse
|
|
|
|
|
old-track-mouse))))))))))
|
|
|
|
|
(eat-term-input-event eat--terminal n e))))
|
|
|
|
|
|
|
|
|
|
(defun eat-quoted-input ()
|
2022-12-04 19:32:14 +06:00
|
|
|
|
"Read a character and send it as INPUT."
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(declare (interactive-only "Use `eat-self-input' instead."))
|
|
|
|
|
(interactive)
|
|
|
|
|
;; HACK: Quick hack to allow inputting `C-g'. Any better way to do
|
|
|
|
|
;; this?
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
(eat-self-input
|
|
|
|
|
1 (let ((inhibit-quit t)
|
|
|
|
|
;; Don't trigger `quit' exiting this `let'.
|
|
|
|
|
(quit-flag nil))
|
|
|
|
|
(read-event))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
2022-12-04 19:32:14 +06:00
|
|
|
|
(defun eat-input-char (character count)
|
|
|
|
|
"Input CHARACTER, COUNT times.
|
|
|
|
|
|
|
|
|
|
Interactively, ask for the character CHARACTER to input. The numeric prefix
|
|
|
|
|
argument COUNT specifies how many times to insert CHARACTER."
|
|
|
|
|
(declare (interactive-only "Use `eat-self-input' instead."))
|
|
|
|
|
(interactive (list (read-char-by-name
|
|
|
|
|
"Insert character (Unicode name or hex): ")
|
|
|
|
|
(prefix-numeric-value current-prefix-arg)))
|
|
|
|
|
(eat-self-input count character))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defun eat-yank (&optional arg)
|
|
|
|
|
"Same as `yank', but for Eat.
|
|
|
|
|
|
|
|
|
|
ARG is passed to `yank', which see."
|
|
|
|
|
(interactive "*P")
|
|
|
|
|
(when eat--terminal
|
2022-12-12 14:00:57 +06:00
|
|
|
|
(funcall eat--synchronize-scroll-function
|
|
|
|
|
(eat--synchronize-scroll-windows 'force-selected))
|
2022-12-10 15:37:09 +06:00
|
|
|
|
(eat-send-string-as-yank
|
2022-12-11 18:40:27 +06:00
|
|
|
|
eat--terminal
|
|
|
|
|
(let ((yank-hook (bound-and-true-p yank-transform-functions)))
|
|
|
|
|
(with-temp-buffer
|
|
|
|
|
(setq-local yank-transform-functions yank-hook)
|
|
|
|
|
(yank arg)
|
|
|
|
|
(buffer-string))))))
|
2022-12-10 15:37:09 +06:00
|
|
|
|
|
|
|
|
|
(defun eat-yank-from-kill-ring (string &optional arg)
|
|
|
|
|
"Same as `yank-from-kill-ring', but for Eat.
|
|
|
|
|
|
|
|
|
|
STRING and ARG are passed to `yank-pop', which see."
|
|
|
|
|
(interactive (list (read-from-kill-ring "Yank from kill-ring: ")
|
|
|
|
|
current-prefix-arg))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when eat--terminal
|
2022-12-12 14:00:57 +06:00
|
|
|
|
(funcall eat--synchronize-scroll-function
|
|
|
|
|
(eat--synchronize-scroll-windows 'force-selected))
|
2022-12-10 15:37:09 +06:00
|
|
|
|
(eat-send-string-as-yank
|
2022-12-11 18:40:27 +06:00
|
|
|
|
eat--terminal
|
|
|
|
|
(let ((yank-hook (bound-and-true-p yank-transform-functions)))
|
|
|
|
|
(with-temp-buffer
|
|
|
|
|
(setq-local yank-transform-functions yank-hook)
|
|
|
|
|
(yank-from-kill-ring string arg)
|
|
|
|
|
(buffer-string))))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
2023-01-15 22:22:13 +06:00
|
|
|
|
(defun eat-xterm-paste (event)
|
|
|
|
|
"Handle paste operation EVENT from XTerm."
|
|
|
|
|
(interactive "e")
|
|
|
|
|
(unless (eq (car-safe event) 'xterm-paste)
|
2023-01-19 15:45:44 +06:00
|
|
|
|
(error "`eat-xterm-paste' must be bind to `xterm-paste' event"))
|
2023-01-15 22:22:13 +06:00
|
|
|
|
(let ((pasted-text (nth 1 event)))
|
|
|
|
|
(if (bound-and-true-p xterm-store-paste-on-kill-ring)
|
|
|
|
|
;; Put the text onto the kill ring and then insert it into the
|
|
|
|
|
;; buffer.
|
|
|
|
|
(let ((interprogram-paste-function (lambda () pasted-text)))
|
|
|
|
|
(eat-yank))
|
|
|
|
|
;; Insert the text without putting it onto the kill ring.
|
|
|
|
|
(eat-send-string-as-yank eat--terminal pasted-text))))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; When changing these keymaps, be sure to update the manual, README
|
|
|
|
|
;; and commentary.
|
|
|
|
|
(defvar eat-mode-map
|
|
|
|
|
(let ((map (make-sparse-keymap)))
|
|
|
|
|
(define-key map [?\C-c ?\M-d] #'eat-char-mode)
|
|
|
|
|
(define-key map [?\C-c ?\C-j] #'eat-semi-char-mode)
|
|
|
|
|
(define-key map [?\C-c ?\C-k] #'eat-kill-process)
|
2022-12-06 22:03:33 +06:00
|
|
|
|
(define-key map [?\C-c ?\C-p] #'eat-previous-shell-prompt)
|
|
|
|
|
(define-key map [?\C-c ?\C-n] #'eat-next-shell-prompt)
|
2023-01-15 22:22:13 +06:00
|
|
|
|
(define-key map [xterm-paste] #'ignore)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
map)
|
|
|
|
|
"Keymap for Eat mode.")
|
|
|
|
|
|
2023-01-16 12:11:25 +06:00
|
|
|
|
(defun eat--prepare-semi-char-mode-map ()
|
|
|
|
|
"Prepare `eat-semi-char-mode-map'."
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(let ((map (eat-term-make-keymap
|
2023-01-16 12:11:25 +06:00
|
|
|
|
#'eat-self-input '(:ascii :arrow :navigation)
|
|
|
|
|
`([?\C-c] [?\C-q] [?\C-y] [?\e ?y]
|
|
|
|
|
,@eat-semi-char-non-bound-keys))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(define-key map [?\C-q] #'eat-quoted-input)
|
|
|
|
|
(define-key map [?\C-y] #'eat-yank)
|
2022-12-10 15:37:09 +06:00
|
|
|
|
(define-key map [?\M-y] #'eat-yank-from-kill-ring)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(define-key map [?\C-c ?\C-c] #'eat-self-input)
|
|
|
|
|
(define-key map [?\C-c ?\C-e] #'eat-emacs-mode)
|
2022-12-04 19:32:14 +06:00
|
|
|
|
(define-key map [remap insert-char] #'eat-input-char)
|
2023-01-15 22:22:13 +06:00
|
|
|
|
(define-key map [xterm-paste] #'eat-xterm-paste)
|
2023-01-16 12:11:25 +06:00
|
|
|
|
map))
|
|
|
|
|
|
|
|
|
|
(defvar eat-semi-char-mode-map (ignore-errors
|
|
|
|
|
(eat--prepare-semi-char-mode-map))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
"Keymap for Eat semi-char mode.")
|
|
|
|
|
|
2023-01-19 15:45:44 +06:00
|
|
|
|
(defun eat-update-semi-char-mode-map ()
|
|
|
|
|
"Update \"semi-char\" keybinding mode's keymap."
|
|
|
|
|
(setq eat-semi-char-mode-map (eat--prepare-semi-char-mode-map)))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defvar eat-char-mode-map
|
|
|
|
|
(let ((map (eat-term-make-keymap
|
2023-01-16 12:11:25 +06:00
|
|
|
|
#'eat-self-input '(:ascii :arrow :navigation :function)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
'([?\e ?\C-m]))))
|
|
|
|
|
(define-key map [?\C-\M-m] #'eat-semi-char-mode)
|
2023-01-15 22:22:13 +06:00
|
|
|
|
(define-key map [xterm-paste] #'eat-xterm-paste)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
map)
|
|
|
|
|
"Keymap for Eat char mode.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--mouse-click-mode-map
|
|
|
|
|
(eat-term-make-keymap #'eat-self-input '(:mouse-click) nil)
|
|
|
|
|
"Keymap for `eat--mouse-click-mode'.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--mouse-modifier-click-mode-map
|
|
|
|
|
(eat-term-make-keymap #'eat-self-input '(:mouse-modifier) nil)
|
|
|
|
|
"Keymap for `eat--mouse-modifier-click-mode'.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--mouse-movement-mode-map
|
|
|
|
|
(eat-term-make-keymap #'eat-self-input '(:mouse-movement) nil)
|
|
|
|
|
"Keymap for `eat--mouse-movement-mode'.")
|
|
|
|
|
|
|
|
|
|
(define-minor-mode eat--semi-char-mode
|
|
|
|
|
"Minor mode for semi-char mode keymap."
|
|
|
|
|
:interactive nil
|
|
|
|
|
:keymap eat-semi-char-mode-map)
|
|
|
|
|
|
|
|
|
|
(define-minor-mode eat--char-mode
|
|
|
|
|
"Minor mode for char mode keymap."
|
|
|
|
|
:interactive nil
|
|
|
|
|
:keymap eat-char-mode-map)
|
|
|
|
|
|
|
|
|
|
(define-minor-mode eat--mouse-click-mode
|
|
|
|
|
"Minor mode for mouse click keymap."
|
|
|
|
|
:interactive nil)
|
|
|
|
|
|
|
|
|
|
(define-minor-mode eat--mouse-modifier-click-mode
|
|
|
|
|
"Minor mode for mouse click with modifiers keymap."
|
|
|
|
|
:interactive nil)
|
|
|
|
|
|
|
|
|
|
(define-minor-mode eat--mouse-movement-mode
|
|
|
|
|
"Minor mode for mouse movement keymap."
|
|
|
|
|
:interactive nil)
|
|
|
|
|
|
|
|
|
|
(defun eat-emacs-mode ()
|
|
|
|
|
"Switch to Emacs keybindings mode."
|
|
|
|
|
(interactive)
|
|
|
|
|
(eat--semi-char-mode -1)
|
|
|
|
|
(eat--char-mode -1)
|
|
|
|
|
(setq buffer-read-only t)
|
|
|
|
|
(eat--grab-mouse nil eat--mouse-grabbing-type)
|
|
|
|
|
(force-mode-line-update))
|
|
|
|
|
|
|
|
|
|
(defun eat-semi-char-mode ()
|
|
|
|
|
"Switch to semi-char mode."
|
|
|
|
|
(interactive)
|
2022-11-29 01:05:32 +06:00
|
|
|
|
(unless eat--terminal
|
|
|
|
|
(error "Process not running"))
|
|
|
|
|
(setq buffer-read-only nil)
|
|
|
|
|
(eat--char-mode -1)
|
|
|
|
|
(eat--semi-char-mode +1)
|
|
|
|
|
(eat--grab-mouse nil eat--mouse-grabbing-type)
|
|
|
|
|
(force-mode-line-update))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat-char-mode ()
|
|
|
|
|
"Switch to char mode."
|
|
|
|
|
(interactive)
|
2022-11-29 01:05:32 +06:00
|
|
|
|
(unless eat--terminal
|
|
|
|
|
(error "Process not running"))
|
|
|
|
|
(setq buffer-read-only nil)
|
|
|
|
|
(eat--semi-char-mode -1)
|
|
|
|
|
(eat--char-mode +1)
|
|
|
|
|
(eat--grab-mouse nil eat--mouse-grabbing-type)
|
|
|
|
|
(force-mode-line-update))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defvar eat--eshell-semi-char-mode)
|
|
|
|
|
(defvar eat--eshell-char-mode)
|
|
|
|
|
|
|
|
|
|
(defun eat--grab-mouse (_ mode)
|
|
|
|
|
"Grab mouse.
|
|
|
|
|
|
|
|
|
|
MODE should one of:
|
|
|
|
|
|
|
|
|
|
nil Disable mouse.
|
|
|
|
|
`:click' Pass `mouse-1', `mouse-2', and `mouse-3'
|
|
|
|
|
clicks.
|
|
|
|
|
`:modifier-click' Pass all mouse clicks, including control,
|
|
|
|
|
meta and shift modifiers.
|
|
|
|
|
`:drag' All of :modifier-click, plus dragging
|
|
|
|
|
(moving mouse while pressed) information.
|
|
|
|
|
`:all' Pass all mouse events, including movement.
|
|
|
|
|
Any other value Disable mouse."
|
|
|
|
|
(setq eat--mouse-grabbing-type mode)
|
|
|
|
|
(pcase (and eat-enable-mouse
|
|
|
|
|
(or eat--semi-char-mode
|
|
|
|
|
eat--char-mode
|
|
|
|
|
eat--eshell-semi-char-mode
|
|
|
|
|
eat--eshell-char-mode)
|
|
|
|
|
mode)
|
|
|
|
|
(:all
|
|
|
|
|
(setq track-mouse t)
|
|
|
|
|
(eat--mouse-click-mode -1)
|
|
|
|
|
(eat--mouse-modifier-click-mode +1)
|
|
|
|
|
(eat--mouse-movement-mode +1))
|
|
|
|
|
((or :modifier-click :drag)
|
|
|
|
|
(setq track-mouse nil)
|
|
|
|
|
(eat--mouse-click-mode -1)
|
|
|
|
|
(eat--mouse-movement-mode -1)
|
|
|
|
|
(eat--mouse-modifier-click-mode +1))
|
|
|
|
|
(:click
|
|
|
|
|
(setq track-mouse nil)
|
|
|
|
|
(eat--mouse-modifier-click-mode -1)
|
|
|
|
|
(eat--mouse-movement-mode -1)
|
|
|
|
|
(eat--mouse-click-mode +1))
|
|
|
|
|
(_
|
|
|
|
|
(setq track-mouse nil)
|
|
|
|
|
(eat--mouse-click-mode -1)
|
|
|
|
|
(eat--mouse-modifier-click-mode -1)
|
|
|
|
|
(eat--mouse-movement-mode -1))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;;; Major Mode.
|
|
|
|
|
|
2022-12-12 14:00:57 +06:00
|
|
|
|
(defun eat--synchronize-scroll-windows (&optional force-selected)
|
|
|
|
|
"Return the list of windows whose scrolling should be synchronized.
|
|
|
|
|
|
|
|
|
|
When FORCE-SELECTED is non-nil, always include `buffer' and the
|
|
|
|
|
selected window in the list if the window is showing the current
|
|
|
|
|
buffer."
|
|
|
|
|
`(,@(and (or force-selected
|
|
|
|
|
eat--char-mode
|
|
|
|
|
(= (eat-term-display-cursor eat--terminal) (point)))
|
|
|
|
|
'(buffer))
|
|
|
|
|
,@(seq-filter
|
|
|
|
|
(lambda (window)
|
|
|
|
|
(or (and force-selected (eq window (selected-window)))
|
|
|
|
|
(= (eat-term-display-cursor eat--terminal)
|
|
|
|
|
(window-point window))))
|
|
|
|
|
(get-buffer-window-list))))
|
|
|
|
|
|
|
|
|
|
(defun eat--synchronize-scroll (windows)
|
|
|
|
|
"Synchronize scrolling and point between terminal and WINDOWS.
|
|
|
|
|
|
|
|
|
|
WINDOWS is a list of windows. WINDOWS may also contain the special
|
|
|
|
|
symbol `buffer', in which case the point of current buffer is set."
|
|
|
|
|
(dolist (window windows)
|
|
|
|
|
(if (eq window 'buffer)
|
|
|
|
|
(goto-char (eat-term-display-cursor eat--terminal))
|
|
|
|
|
(set-window-start
|
|
|
|
|
window (eat-term-display-beginning eat--terminal))
|
|
|
|
|
(set-window-point
|
|
|
|
|
window (eat-term-display-cursor eat--terminal)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--setup-glyphless-chars ()
|
|
|
|
|
"Setup the display of glyphless characters."
|
|
|
|
|
(setq-local glyphless-char-display
|
|
|
|
|
(copy-sequence (default-value 'glyphless-char-display)))
|
|
|
|
|
(set-char-table-extra-slot
|
|
|
|
|
glyphless-char-display 0
|
|
|
|
|
(if (display-graphic-p) 'empty-box 'thin-space)))
|
|
|
|
|
|
|
|
|
|
(defun eat--filter-buffer-substring (begin end &optional delete)
|
|
|
|
|
"Filter buffer substring from BEGIN to END and return that.
|
|
|
|
|
|
|
|
|
|
When DELETE is given and non-nil, delete the text between BEGIN and
|
|
|
|
|
END if it's safe to do so."
|
|
|
|
|
(let ((str (eat-term-filter-string (buffer-substring begin end))))
|
|
|
|
|
(when (and delete
|
|
|
|
|
(or (not eat--terminal)
|
|
|
|
|
(and (<= (eat-term-end eat--terminal) begin)
|
|
|
|
|
(<= (eat-term-end eat--terminal) end))
|
|
|
|
|
(and (<= begin (eat-term-beginning eat--terminal))
|
|
|
|
|
(<= end (eat-term-beginning eat--terminal)))))
|
|
|
|
|
(delete-region begin end))
|
|
|
|
|
str))
|
|
|
|
|
|
|
|
|
|
(define-derived-mode eat-mode fundamental-mode "Eat"
|
|
|
|
|
"Major mode for Eat."
|
|
|
|
|
:group 'eat-ui
|
2022-12-06 21:30:01 +06:00
|
|
|
|
(mapc #'make-local-variable
|
|
|
|
|
'(buffer-read-only
|
|
|
|
|
buffer-undo-list
|
|
|
|
|
filter-buffer-substring-function
|
|
|
|
|
mode-line-process
|
|
|
|
|
mode-line-buffer-identification
|
|
|
|
|
glyphless-char-display
|
|
|
|
|
cursor-type
|
|
|
|
|
track-mouse
|
|
|
|
|
eat--terminal
|
|
|
|
|
eat--synchronize-scroll-function
|
|
|
|
|
eat--mouse-grabbing-type
|
|
|
|
|
eat--shell-command-status
|
|
|
|
|
eat--shell-prompt-begin
|
|
|
|
|
eat--shell-prompt-mark
|
|
|
|
|
eat--shell-prompt-mark-overlays
|
|
|
|
|
eat--pending-output-chunks
|
|
|
|
|
eat--output-queue-first-chunk-time
|
|
|
|
|
eat--process-output-queue-timer
|
2022-12-07 11:06:44 +06:00
|
|
|
|
eat--shell-prompt-annotation-correction-timer))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; This is intended; input methods don't work on read-only buffers.
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setq buffer-read-only nil)
|
|
|
|
|
(setq buffer-undo-list t)
|
|
|
|
|
(setq eat--synchronize-scroll-function #'eat--synchronize-scroll)
|
|
|
|
|
(setq filter-buffer-substring-function
|
|
|
|
|
#'eat--filter-buffer-substring)
|
|
|
|
|
(setq eat--mouse-grabbing-type nil)
|
|
|
|
|
(setq mode-line-process
|
2022-09-02 20:03:33 +06:00
|
|
|
|
'(""
|
|
|
|
|
(:eval
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(when eat--terminal
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(cond
|
|
|
|
|
(eat--semi-char-mode
|
2022-11-29 00:28:03 +06:00
|
|
|
|
'("["
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(:propertize
|
|
|
|
|
"semi-char"
|
2022-11-29 00:28:03 +06:00
|
|
|
|
help-echo "mouse-1: Switch to char mode, \
|
|
|
|
|
mouse-3: Switch to emacs mode"
|
2022-09-02 20:03:33 +06:00
|
|
|
|
mouse-face mode-line-highlight
|
|
|
|
|
local-map
|
|
|
|
|
(keymap
|
|
|
|
|
(mode-line
|
|
|
|
|
. (keymap
|
|
|
|
|
(down-mouse-1 . eat-char-mode)
|
|
|
|
|
(down-mouse-3 . eat-emacs-mode)))))
|
|
|
|
|
"]"))
|
|
|
|
|
(eat--char-mode
|
|
|
|
|
'("["
|
|
|
|
|
(:propertize
|
|
|
|
|
"char"
|
2022-11-29 00:28:03 +06:00
|
|
|
|
help-echo "mouse-1: Switch to semi-char mode, \
|
|
|
|
|
mouse-3: Switch to emacs mode"
|
2022-09-02 20:03:33 +06:00
|
|
|
|
mouse-face mode-line-highlight
|
|
|
|
|
local-map
|
|
|
|
|
(keymap
|
|
|
|
|
(mode-line
|
|
|
|
|
. (keymap
|
|
|
|
|
(down-mouse-1 . eat-semi-char-mode)
|
|
|
|
|
(down-mouse-3 . eat-emacs-mode)))))
|
|
|
|
|
"]"))
|
|
|
|
|
(t
|
2022-11-29 00:28:03 +06:00
|
|
|
|
'("["
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(:propertize
|
|
|
|
|
"emacs"
|
2022-11-29 00:28:03 +06:00
|
|
|
|
help-echo "mouse-1: Switch to semi char mode, \
|
|
|
|
|
mouse-3: Switch to char mode"
|
2022-09-02 20:03:33 +06:00
|
|
|
|
mouse-face mode-line-highlight
|
|
|
|
|
local-map
|
|
|
|
|
(keymap
|
|
|
|
|
(mode-line
|
|
|
|
|
. (keymap
|
|
|
|
|
(down-mouse-1 . eat-semi-char-mode)
|
|
|
|
|
(down-mouse-3 . eat-char-mode)))))
|
|
|
|
|
"]")))))
|
|
|
|
|
":%s"))
|
|
|
|
|
(setq mode-line-buffer-identification
|
|
|
|
|
`(12 (""
|
|
|
|
|
,(nconc
|
|
|
|
|
(propertized-buffer-identification "%b")
|
|
|
|
|
'(" "
|
|
|
|
|
(:propertize
|
|
|
|
|
(:eval
|
|
|
|
|
(when (and eat--terminal
|
|
|
|
|
(not (string-empty-p (eat-term-title
|
|
|
|
|
eat--terminal))))
|
2022-12-07 12:00:41 +06:00
|
|
|
|
(format "(%s)" (eat-term-title eat--terminal))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
help-echo "Title"))))))
|
|
|
|
|
(eat-emacs-mode)
|
|
|
|
|
;; Make sure glyphless character don't display a huge box glyph,
|
|
|
|
|
;; that would break the display.
|
|
|
|
|
(eat--setup-glyphless-chars)
|
|
|
|
|
(when eat-enable-blinking-text
|
2022-12-06 21:30:01 +06:00
|
|
|
|
(eat-blink-mode +1))
|
|
|
|
|
(when eat-enable-shell-prompt-annotation
|
|
|
|
|
(let ((margin-width
|
|
|
|
|
(max
|
|
|
|
|
(string-width
|
|
|
|
|
eat-shell-prompt-annotation-running-margin-indicator)
|
|
|
|
|
(string-width
|
|
|
|
|
eat-shell-prompt-annotation-success-margin-indicator)
|
|
|
|
|
(string-width
|
|
|
|
|
eat-shell-prompt-annotation-failure-margin-indicator))))
|
|
|
|
|
(pcase-exhaustive eat-shell-prompt-annotation-position
|
|
|
|
|
('left-margin
|
|
|
|
|
(setq left-margin-width margin-width))
|
|
|
|
|
('right-margin
|
|
|
|
|
(setq right-margin-width margin-width))))
|
|
|
|
|
;; Make sure the marginal area is resized.
|
|
|
|
|
(dolist (win (get-buffer-window-list))
|
|
|
|
|
(set-window-buffer win (current-buffer)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;;; Process Handling.
|
|
|
|
|
|
|
|
|
|
(defvar eat--pending-output-chunks nil
|
|
|
|
|
"The list of pending output chunks.
|
|
|
|
|
|
|
|
|
|
The output chunks are pushed, so last output appears first.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--output-queue-first-chunk-time nil
|
|
|
|
|
"Time when the first chunk in the current output queue was pushed.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--process-output-queue-timer nil
|
|
|
|
|
"Timer to process output queue.")
|
|
|
|
|
|
2022-12-07 11:06:44 +06:00
|
|
|
|
(defvar eat--shell-prompt-annotation-correction-timer nil
|
|
|
|
|
"Timer to correct shell prompt annotations.")
|
2022-12-06 21:30:01 +06:00
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defun eat-kill-process ()
|
|
|
|
|
"Kill Eat process in current buffer."
|
|
|
|
|
(interactive)
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(when-let* ((eat--terminal)
|
|
|
|
|
(proc (eat-term-parameter eat--terminal 'eat--process)))
|
|
|
|
|
(delete-process proc)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--send-string (process string)
|
|
|
|
|
"Send to PROCESS the contents of STRING as input.
|
|
|
|
|
|
|
|
|
|
This is equivalent to `process-send-string', except that long input
|
|
|
|
|
strings are broken up into chunks of size `eat-input-chunk-size'.
|
|
|
|
|
Processes are given a chance to output between chunks. This can help
|
|
|
|
|
prevent processes from hanging when you send them long inputs on some
|
|
|
|
|
OS's."
|
|
|
|
|
(let ((i 0)
|
|
|
|
|
(j eat-input-chunk-size)
|
|
|
|
|
(l (length string)))
|
|
|
|
|
(while (< i l)
|
|
|
|
|
(process-send-string process (substring string i (min j l)))
|
|
|
|
|
(accept-process-output)
|
|
|
|
|
(cl-incf i eat-input-chunk-size)
|
|
|
|
|
(cl-incf j eat-input-chunk-size))))
|
|
|
|
|
|
|
|
|
|
(defun eat--send-input (_ input)
|
|
|
|
|
"Send INPUT to subprocess."
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(when-let* ((eat--terminal)
|
|
|
|
|
(proc (eat-term-parameter eat--terminal 'eat--process)))
|
|
|
|
|
(eat--send-string proc input)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--process-output-queue (buffer)
|
|
|
|
|
"Process the output queue on BUFFER."
|
|
|
|
|
(when (buffer-live-p buffer)
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(let ((inhibit-quit t) ; Don't disturb!
|
|
|
|
|
(inhibit-read-only t)
|
|
|
|
|
(inhibit-modification-hooks t)
|
2022-12-12 14:00:57 +06:00
|
|
|
|
(sync-windows (eat--synchronize-scroll-windows)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when eat--process-output-queue-timer
|
|
|
|
|
(cancel-timer eat--process-output-queue-timer))
|
|
|
|
|
(setq eat--output-queue-first-chunk-time nil)
|
|
|
|
|
(let ((queue eat--pending-output-chunks))
|
|
|
|
|
(setq eat--pending-output-chunks nil)
|
|
|
|
|
(dolist (output (nreverse queue))
|
|
|
|
|
(eat-term-process-output eat--terminal output)))
|
|
|
|
|
(eat-term-redisplay eat--terminal)
|
|
|
|
|
;; Truncate output of previous dead processes.
|
|
|
|
|
(when (and eat-term-scrollback-size
|
|
|
|
|
(< eat-term-scrollback-size
|
|
|
|
|
(- (point) (point-min))))
|
|
|
|
|
(delete-region
|
|
|
|
|
(point-min)
|
|
|
|
|
(max (point-min)
|
|
|
|
|
(- (eat-term-display-beginning eat--terminal)
|
|
|
|
|
eat-term-scrollback-size))))
|
2022-12-07 11:17:20 +06:00
|
|
|
|
(setq eat--shell-prompt-annotation-correction-timer
|
|
|
|
|
(run-with-timer
|
|
|
|
|
eat-shell-prompt-annotation-correction-delay
|
|
|
|
|
nil #'eat--correct-shell-prompt-mark-overlays
|
|
|
|
|
buffer))
|
2022-12-12 14:00:57 +06:00
|
|
|
|
(funcall eat--synchronize-scroll-function sync-windows)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--filter (process output)
|
|
|
|
|
"Handle OUTPUT from PROCESS."
|
|
|
|
|
(when (buffer-live-p (process-buffer process))
|
|
|
|
|
(with-current-buffer (process-buffer process)
|
|
|
|
|
(when eat--process-output-queue-timer
|
|
|
|
|
(cancel-timer eat--process-output-queue-timer))
|
2022-12-07 11:06:44 +06:00
|
|
|
|
(when eat--shell-prompt-annotation-correction-timer
|
|
|
|
|
(cancel-timer eat--shell-prompt-annotation-correction-timer))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(unless eat--output-queue-first-chunk-time
|
|
|
|
|
(setq eat--output-queue-first-chunk-time (current-time)))
|
|
|
|
|
(push output eat--pending-output-chunks)
|
|
|
|
|
(let ((time-left
|
|
|
|
|
(- eat-maximum-latency
|
|
|
|
|
(float-time
|
|
|
|
|
(time-subtract
|
|
|
|
|
nil eat--output-queue-first-chunk-time)))))
|
|
|
|
|
(if (<= time-left 0)
|
|
|
|
|
(eat--process-output-queue (current-buffer))
|
|
|
|
|
(setq eat--process-output-queue-timer
|
|
|
|
|
(run-with-timer
|
|
|
|
|
(min time-left eat-minimum-latency) nil
|
|
|
|
|
#'eat--process-output-queue (current-buffer))))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--sentinel (process message)
|
|
|
|
|
"Sentinel for Eat buffers.
|
|
|
|
|
|
|
|
|
|
PROCESS is the process and MESSAGE is the description of what happened
|
|
|
|
|
to it."
|
|
|
|
|
(let ((buffer (process-buffer process)))
|
|
|
|
|
(when (memq (process-status process) '(signal exit))
|
|
|
|
|
(if (buffer-live-p buffer)
|
|
|
|
|
(if eat-kill-buffer-on-exit
|
|
|
|
|
(kill-buffer buffer)
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(let ((inhibit-read-only t))
|
2022-12-08 15:58:20 +06:00
|
|
|
|
(when eat--process-output-queue-timer
|
|
|
|
|
(cancel-timer eat--process-output-queue-timer)
|
|
|
|
|
(setq eat--process-output-queue-timer nil))
|
|
|
|
|
(eat--process-output-queue buffer)
|
|
|
|
|
(when eat--shell-prompt-annotation-correction-timer
|
|
|
|
|
(cancel-timer
|
|
|
|
|
eat--shell-prompt-annotation-correction-timer)
|
|
|
|
|
(setq eat--shell-prompt-annotation-correction-timer
|
|
|
|
|
nil))
|
|
|
|
|
(when eat-enable-shell-prompt-annotation
|
|
|
|
|
(eat--correct-shell-prompt-mark-overlays buffer)
|
|
|
|
|
(setq eat--shell-command-status 0)
|
|
|
|
|
(setq eat--shell-prompt-begin nil)
|
|
|
|
|
(setq eat--shell-prompt-mark nil)
|
|
|
|
|
(setq eat--shell-prompt-mark-overlays nil))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat-emacs-mode)
|
|
|
|
|
(delete-process process)
|
|
|
|
|
(eat-term-delete eat--terminal)
|
|
|
|
|
(setq eat--terminal nil)
|
|
|
|
|
(eat--set-cursor nil :default)
|
|
|
|
|
(eat--grab-mouse nil nil)
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
(insert "\nProcess " (process-name process) " "
|
|
|
|
|
message)
|
|
|
|
|
(setq buffer-read-only nil))))
|
|
|
|
|
(set-process-buffer process nil)))))
|
|
|
|
|
|
|
|
|
|
(defun eat--adjust-process-window-size (process windows)
|
|
|
|
|
"Resize process window and terminal. Return new dimensions.
|
|
|
|
|
|
|
|
|
|
PROCESS is the process whose window to resize, and WINDOWS is the list
|
|
|
|
|
of window displaying PROCESS's buffer."
|
2022-11-28 12:40:19 +06:00
|
|
|
|
(let ((size (funcall window-adjust-process-window-size-function
|
|
|
|
|
process windows)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(when size
|
|
|
|
|
(let ((width (max (car size) 1))
|
|
|
|
|
(height (max (cdr size) 1))
|
|
|
|
|
(inhibit-read-only t)
|
2022-12-12 14:00:57 +06:00
|
|
|
|
(sync-windows (eat--synchronize-scroll-windows)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat-term-resize eat--terminal width height)
|
|
|
|
|
(eat-term-redisplay eat--terminal)
|
2022-12-12 14:00:57 +06:00
|
|
|
|
(funcall eat--synchronize-scroll-function sync-windows)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
size))
|
|
|
|
|
|
|
|
|
|
;; Adapted from Term.
|
|
|
|
|
(defun eat-exec (buffer name command startfile switches)
|
|
|
|
|
"Start up a process in BUFFER for Eat mode.
|
|
|
|
|
|
|
|
|
|
Run COMMAND with SWITCHES. Set NAME as the name of the process.
|
|
|
|
|
Blast any old process running in the buffer. Don't set the buffer
|
|
|
|
|
mode. You can use this to cheaply run a series of processes in the
|
|
|
|
|
same Eat buffer. The hook `eat-exec-hook' is run after each exec."
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(let ((inhibit-read-only t))
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(when-let*
|
|
|
|
|
((eat--terminal)
|
|
|
|
|
(proc (eat-term-parameter eat--terminal 'eat--process)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(let ((eat-kill-buffer-on-exit nil))
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(delete-process proc)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Ensure final newline.
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
(unless (or (= (point-min) (point-max))
|
|
|
|
|
(= (char-before (point-max)) ?\n))
|
|
|
|
|
(insert ?\n))
|
|
|
|
|
(unless (= (point-min) (point-max))
|
|
|
|
|
(insert "\n\n"))
|
|
|
|
|
(setq eat--terminal (eat-term-make buffer (point)))
|
|
|
|
|
(eat-semi-char-mode)
|
2022-11-28 23:22:52 +06:00
|
|
|
|
(when-let* ((window (get-buffer-window nil t)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(with-selected-window window
|
|
|
|
|
(eat-term-resize eat--terminal (window-max-chars-per-line)
|
2022-12-04 22:49:56 +06:00
|
|
|
|
(floor (window-screen-lines)))))
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setf (eat-term-input-function eat--terminal) #'eat--send-input)
|
|
|
|
|
(setf (eat-term-set-cursor-function eat--terminal)
|
|
|
|
|
#'eat--set-cursor)
|
|
|
|
|
(setf (eat-term-grab-mouse-function eat--terminal)
|
|
|
|
|
#'eat--grab-mouse)
|
|
|
|
|
(setf (eat-term-manipulate-selection-function eat--terminal)
|
|
|
|
|
#'eat--manipulate-kill-ring)
|
|
|
|
|
(setf (eat-term-ring-bell-function eat--terminal) #'eat--bell)
|
|
|
|
|
(setf (eat-term-set-cwd-function eat--terminal) #'eat--set-cwd)
|
|
|
|
|
(setf (eat-term-prompt-start-function eat--terminal)
|
|
|
|
|
#'eat--pre-prompt)
|
|
|
|
|
(setf (eat-term-prompt-end-function eat--terminal)
|
|
|
|
|
#'eat--post-prompt)
|
|
|
|
|
(setf (eat-term-set-cmd-function eat--terminal) #'eat--set-cmd)
|
|
|
|
|
(setf (eat-term-cmd-start-function eat--terminal)
|
|
|
|
|
#'eat--pre-cmd)
|
|
|
|
|
(setf (eat-term-cmd-finish-function eat--terminal)
|
2022-12-06 21:30:01 +06:00
|
|
|
|
#'eat--set-cmd-status)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Crank up a new process.
|
|
|
|
|
(let* ((size (eat-term-size eat--terminal))
|
|
|
|
|
(process-environment
|
|
|
|
|
(nconc
|
|
|
|
|
(list
|
|
|
|
|
(concat "TERM=" (eat-term-name))
|
|
|
|
|
(concat "TERMINFO=" eat-term-terminfo-directory)
|
2022-12-03 11:14:01 +06:00
|
|
|
|
(concat "INSIDE_EMACS=" eat-term-inside-emacs)
|
|
|
|
|
(concat "EAT_SHELL_INTEGRATION_DIR="
|
|
|
|
|
eat-term-shell-integration-directory))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
process-environment))
|
|
|
|
|
(process-connection-type t)
|
|
|
|
|
;; We should suppress conversion of end-of-line format.
|
|
|
|
|
(inhibit-eol-conversion t)
|
|
|
|
|
(process
|
|
|
|
|
(make-process
|
|
|
|
|
:name name
|
|
|
|
|
:buffer buffer
|
|
|
|
|
:command `("/usr/bin/env" "sh" "-c"
|
|
|
|
|
,(format "stty -nl echo rows %d columns \
|
|
|
|
|
%d sane 2>%s ; if [ $1 = .. ]; then shift; fi; exec \"$@\""
|
|
|
|
|
(cdr size) (car size)
|
|
|
|
|
null-device)
|
|
|
|
|
".."
|
|
|
|
|
,command ,@switches)
|
|
|
|
|
:filter #'eat--filter
|
|
|
|
|
:sentinel #'eat--sentinel
|
|
|
|
|
:file-handler t)))
|
|
|
|
|
(process-put process 'adjust-window-size-function
|
|
|
|
|
#'eat--adjust-process-window-size)
|
2023-02-07 17:13:10 +06:00
|
|
|
|
(set-process-query-on-exit-flag
|
|
|
|
|
process eat-query-before-killing-running-terminal)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Jump to the end, and set the process mark.
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
(set-marker (process-mark process) (point))
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(setf (eat-term-parameter eat--terminal 'eat--process)
|
|
|
|
|
process)
|
|
|
|
|
(setf (eat-term-parameter eat--terminal 'eat--input-process)
|
|
|
|
|
process)
|
|
|
|
|
(setf (eat-term-parameter eat--terminal 'eat--output-process)
|
|
|
|
|
process)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Feed it the startfile.
|
|
|
|
|
(when startfile
|
2023-03-20 23:54:33 +06:00
|
|
|
|
;; This is guaranteed to wait long enough
|
|
|
|
|
;; but has bad results if the shell does not prompt at all
|
|
|
|
|
;; (while (= size (buffer-size))
|
|
|
|
|
;; (sleep-for 1))
|
|
|
|
|
;; I hope 1 second is enough!
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(sleep-for 1)
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
(insert-file-contents startfile)
|
|
|
|
|
(process-send-string
|
|
|
|
|
process (delete-and-extract-region (point) (point-max)))))
|
|
|
|
|
(eat-term-redisplay eat--terminal)
|
|
|
|
|
(run-hooks 'eat-exec-hook)
|
|
|
|
|
buffer)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;;; Entry Points.
|
|
|
|
|
|
|
|
|
|
(defun eat-make (name program &optional startfile &rest switches)
|
|
|
|
|
"Make a Eat process NAME in a buffer, running PROGRAM.
|
|
|
|
|
|
|
|
|
|
The name of the buffer is made by surrounding NAME with `*'s. If
|
|
|
|
|
there is already a running process in that buffer, it is not
|
|
|
|
|
restarted. Optional third arg STARTFILE is the name of a file to send
|
|
|
|
|
the contents of to the process. SWITCHES are the arguments to
|
|
|
|
|
PROGRAM."
|
|
|
|
|
(let ((buffer (get-buffer-create (concat "*" name "*"))))
|
|
|
|
|
;; If no process, or nuked process, crank up a new one and put
|
|
|
|
|
;; buffer in Eat mode. Otherwise, leave buffer and existing
|
|
|
|
|
;; process alone.
|
|
|
|
|
(when (not (let ((proc (get-buffer-process buffer)))
|
|
|
|
|
(and proc (memq (process-status proc)
|
|
|
|
|
'(run stop open listen connect)))))
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(eat-mode))
|
|
|
|
|
(eat-exec buffer name program startfile switches))
|
|
|
|
|
buffer))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun eat (&optional program arg)
|
|
|
|
|
"Start a new Eat terminal emulator in a buffer.
|
|
|
|
|
|
|
|
|
|
Start a new Eat session, or switch to an already active session.
|
|
|
|
|
Return the buffer selected (or created).
|
|
|
|
|
|
|
|
|
|
With a non-numeric prefix ARG, create a new session.
|
|
|
|
|
|
2023-03-29 23:09:30 +06:00
|
|
|
|
With a numeric prefix ARG (like \\[universal-argument] 42 \\[eat]),
|
2022-09-02 20:03:33 +06:00
|
|
|
|
switch to the session with that number, or create it if it doesn't
|
|
|
|
|
already exist.
|
|
|
|
|
|
2023-03-29 22:39:45 +06:00
|
|
|
|
With double prefix argument ARG, ask for the program to run and run it
|
|
|
|
|
in a newly created session.
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
PROGRAM can be a shell command."
|
2023-03-29 22:39:45 +06:00
|
|
|
|
(interactive
|
|
|
|
|
(list (when (equal current-prefix-arg '(16))
|
|
|
|
|
(read-shell-command "Run program: "
|
|
|
|
|
(or explicit-shell-file-name
|
|
|
|
|
(getenv "ESHELL")
|
|
|
|
|
shell-file-name)))
|
|
|
|
|
current-prefix-arg))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(let ((program (or program (or explicit-shell-file-name
|
|
|
|
|
(getenv "ESHELL")
|
|
|
|
|
shell-file-name)))
|
|
|
|
|
(buffer
|
|
|
|
|
(cond
|
|
|
|
|
((numberp arg)
|
|
|
|
|
(get-buffer-create (format "%s<%d>" eat-buffer-name arg)))
|
|
|
|
|
(arg
|
|
|
|
|
(generate-new-buffer eat-buffer-name))
|
|
|
|
|
(t
|
|
|
|
|
(get-buffer-create eat-buffer-name)))))
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(unless (eq major-mode #'eat-mode)
|
|
|
|
|
(eat-mode))
|
|
|
|
|
(pop-to-buffer-same-window buffer)
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(unless (and eat--terminal
|
|
|
|
|
(eat-term-parameter eat--terminal 'eat--process))
|
2022-12-28 21:46:27 +06:00
|
|
|
|
(eat-exec buffer (buffer-name) "/usr/bin/env" nil
|
|
|
|
|
(list "sh" "-c" program)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
buffer)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;; Eshell integration.
|
|
|
|
|
|
|
|
|
|
;;;;; Input.
|
|
|
|
|
|
|
|
|
|
;; When changing these keymaps, be sure to update the manual, README
|
|
|
|
|
;; and commentary.
|
|
|
|
|
(defvar eat-eshell-emacs-mode-map
|
|
|
|
|
(let ((map (make-sparse-keymap)))
|
|
|
|
|
(define-key map [?\C-c ?\C-j] #'eat-eshell-semi-char-mode)
|
|
|
|
|
(define-key map [remap eshell-toggle-direct-send] ; C-c M-d
|
|
|
|
|
#'eat-eshell-char-mode)
|
2022-12-11 14:44:01 +06:00
|
|
|
|
(define-key map [remap undo] #'undefined) ; Disable `undo'.
|
2023-01-15 22:22:13 +06:00
|
|
|
|
(define-key map [xterm-paste] #'ignore)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
map)
|
2022-12-11 14:41:38 +06:00
|
|
|
|
"Keymap for Eat Eshell \"emacs\" mode.")
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
2023-01-16 12:11:25 +06:00
|
|
|
|
(defun eat--eshell-prepare-semi-char-mode-map ()
|
|
|
|
|
"Prepare `eat-eshell-semi-char-mode-map'."
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(let ((map (eat-term-make-keymap
|
2023-01-16 12:11:25 +06:00
|
|
|
|
#'eat-self-input '(:ascii :arrow :navigation)
|
|
|
|
|
`([?\C-c] [?\C-q] [?\C-y] [?\e ?y]
|
|
|
|
|
,@eat-eshell-semi-char-non-bound-keys))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(define-key map [?\C-q] #'eat-quoted-input)
|
|
|
|
|
(define-key map [?\C-y] #'eat-yank)
|
2022-12-10 15:37:09 +06:00
|
|
|
|
(define-key map [?\M-y] #'eat-yank-from-kill-ring)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(define-key map [?\C-c ?\C-e] #'eat-eshell-emacs-mode)
|
2022-12-04 19:32:14 +06:00
|
|
|
|
(define-key map [remap insert-char] #'eat-input-char)
|
2023-01-15 22:22:13 +06:00
|
|
|
|
(define-key map [xterm-paste] #'eat-xterm-paste)
|
2023-01-16 12:11:25 +06:00
|
|
|
|
map))
|
|
|
|
|
|
|
|
|
|
(defvar eat-eshell-semi-char-mode-map
|
|
|
|
|
(ignore-errors
|
|
|
|
|
(eat--eshell-prepare-semi-char-mode-map))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
"Keymap for Eat Eshell semi-char mode.")
|
|
|
|
|
|
2023-01-19 15:45:44 +06:00
|
|
|
|
(defun eat-eshell-update-semi-char-mode-map ()
|
|
|
|
|
"Update \"semi-char\" keybinding mode's keymap in Eshell."
|
|
|
|
|
(setq eat-eshell-semi-char-mode-map
|
|
|
|
|
(eat--eshell-prepare-semi-char-mode-map)))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defvar eat-eshell-char-mode-map
|
|
|
|
|
(let ((map (eat-term-make-keymap
|
2023-01-16 12:11:25 +06:00
|
|
|
|
#'eat-self-input '(:ascii :arrow :navigation :function)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
'([?\e ?\C-m]))))
|
|
|
|
|
(define-key map [?\C-\M-m] #'eat-eshell-semi-char-mode)
|
2023-01-15 22:22:13 +06:00
|
|
|
|
(define-key map [xterm-paste] #'eat-xterm-paste)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
map)
|
|
|
|
|
"Keymap for Eat Eshell char mode.")
|
|
|
|
|
|
2022-12-11 14:41:38 +06:00
|
|
|
|
(define-minor-mode eat--eshell-process-running-mode
|
|
|
|
|
"Minor mode for \"emacs\" mode keymap when process is running."
|
|
|
|
|
:interactive nil
|
|
|
|
|
:keymap eat-eshell-emacs-mode-map)
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(define-minor-mode eat--eshell-semi-char-mode
|
|
|
|
|
"Minor mode for semi-char mode keymap."
|
|
|
|
|
:interactive nil
|
|
|
|
|
:keymap eat-eshell-semi-char-mode-map
|
|
|
|
|
;; HACK: Some keys like `C-c' are overriden by other keymaps
|
|
|
|
|
;; (possibly by the keymaps of other minor modes), so we also put
|
|
|
|
|
;; the keymap to `minor-mode-overriding-map-alist' to make Emacs
|
|
|
|
|
;; prioritize us.
|
|
|
|
|
(setq minor-mode-overriding-map-alist
|
|
|
|
|
(delete (cons #'eat--eshell-semi-char-mode
|
|
|
|
|
eat-eshell-semi-char-mode-map)
|
|
|
|
|
minor-mode-overriding-map-alist))
|
|
|
|
|
(when eat--eshell-semi-char-mode
|
|
|
|
|
(push (cons #'eat--eshell-semi-char-mode
|
|
|
|
|
eat-eshell-semi-char-mode-map)
|
|
|
|
|
minor-mode-overriding-map-alist)))
|
|
|
|
|
|
|
|
|
|
(define-minor-mode eat--eshell-char-mode
|
|
|
|
|
"Minor mode for char mode keymap."
|
|
|
|
|
:interactive nil
|
|
|
|
|
:keymap eat-eshell-char-mode-map
|
|
|
|
|
;; HACK: Some keys like `C-c' are overriden by other keymaps
|
|
|
|
|
;; (possibly by the keymaps of other minor modes), so we also put
|
|
|
|
|
;; the keymap to `minor-mode-overriding-map-alist' to make Emacs
|
|
|
|
|
;; prioritize us.
|
|
|
|
|
(setq minor-mode-overriding-map-alist
|
|
|
|
|
(delete (cons #'eat--eshell-char-mode
|
|
|
|
|
eat-eshell-char-mode-map)
|
|
|
|
|
minor-mode-overriding-map-alist))
|
|
|
|
|
(when eat--eshell-char-mode
|
|
|
|
|
(push (cons #'eat--eshell-char-mode eat-eshell-char-mode-map)
|
|
|
|
|
minor-mode-overriding-map-alist)))
|
|
|
|
|
|
|
|
|
|
(defun eat-eshell-emacs-mode ()
|
|
|
|
|
"Switch to Emacs keybindings mode."
|
|
|
|
|
(interactive)
|
|
|
|
|
(eat--eshell-semi-char-mode -1)
|
|
|
|
|
(eat--eshell-char-mode -1)
|
|
|
|
|
(setq buffer-read-only t)
|
|
|
|
|
(eat--grab-mouse nil eat--mouse-grabbing-type)
|
|
|
|
|
(force-mode-line-update))
|
|
|
|
|
|
|
|
|
|
(defun eat-eshell-semi-char-mode ()
|
|
|
|
|
"Switch to semi-char mode."
|
|
|
|
|
(interactive)
|
|
|
|
|
(when eat--terminal
|
|
|
|
|
(setq buffer-read-only nil)
|
|
|
|
|
(eat--eshell-char-mode -1)
|
|
|
|
|
(eat--eshell-semi-char-mode +1)
|
|
|
|
|
(eat--grab-mouse nil eat--mouse-grabbing-type)
|
|
|
|
|
(force-mode-line-update)))
|
|
|
|
|
|
|
|
|
|
(defun eat-eshell-char-mode ()
|
|
|
|
|
"Switch to char mode."
|
|
|
|
|
(interactive)
|
|
|
|
|
(when eat--terminal
|
|
|
|
|
(setq buffer-read-only nil)
|
|
|
|
|
(eat--eshell-semi-char-mode -1)
|
|
|
|
|
(eat--eshell-char-mode +1)
|
|
|
|
|
(eat--grab-mouse nil eat--mouse-grabbing-type)
|
|
|
|
|
(force-mode-line-update)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;;; Process Handling.
|
|
|
|
|
|
2022-12-01 01:40:17 +06:00
|
|
|
|
(defvar eat--eshell-invocation-directory nil
|
|
|
|
|
"The directory from where the current process was started.")
|
|
|
|
|
|
2022-11-29 00:48:04 +06:00
|
|
|
|
(defvar eshell-last-output-start) ; In `esh-mode'.
|
|
|
|
|
(defvar eshell-last-output-end) ; In `esh-mode'.
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(declare-function eshell-head-process "esh-cmd" ())
|
|
|
|
|
(declare-function eshell-resume-eval "esh-cmd" ())
|
2022-11-29 00:48:04 +06:00
|
|
|
|
|
2022-11-30 12:29:05 +06:00
|
|
|
|
(defun eat--eshell-term-name (&rest _)
|
|
|
|
|
"Return the value of `TERM' environment variable for Eshell."
|
|
|
|
|
(eat-term-name))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defun eat--eshell-output-filter ()
|
|
|
|
|
"Handle output from subprocess."
|
|
|
|
|
(let ((inhibit-quit t) ; Don't disturb!
|
|
|
|
|
(inhibit-read-only t)
|
|
|
|
|
(str (buffer-substring-no-properties
|
|
|
|
|
eshell-last-output-start
|
|
|
|
|
eshell-last-output-end)))
|
|
|
|
|
(delete-region eshell-last-output-start eshell-last-output-end)
|
2022-12-12 14:00:57 +06:00
|
|
|
|
(let ((sync-windows (eat--synchronize-scroll-windows)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat-term-process-output eat--terminal str)
|
|
|
|
|
(eat-term-redisplay eat--terminal)
|
2022-12-12 14:00:57 +06:00
|
|
|
|
(funcall eat--synchronize-scroll-function sync-windows))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(let ((end (eat-term-end eat--terminal)))
|
|
|
|
|
(set-marker eshell-last-output-start end)
|
|
|
|
|
(set-marker eshell-last-output-end end)
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(set-marker (process-mark (eat-term-parameter
|
|
|
|
|
eat--terminal 'eat--output-process))
|
|
|
|
|
end))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--eshell-setup-proc-and-term (proc)
|
|
|
|
|
"Setup process PROC and a new terminal for it."
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(unless eat--terminal
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(process-put proc 'adjust-window-size-function
|
|
|
|
|
#'eat--adjust-process-window-size)
|
|
|
|
|
(setq eat--terminal (eat-term-make (current-buffer)
|
|
|
|
|
(process-mark proc)))
|
|
|
|
|
(set-marker (process-mark proc) (eat-term-end eat--terminal))
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setf (eat-term-input-function eat--terminal) #'eat--send-input)
|
|
|
|
|
(setf (eat-term-set-cursor-function eat--terminal)
|
|
|
|
|
#'eat--set-cursor)
|
|
|
|
|
(setf (eat-term-grab-mouse-function eat--terminal)
|
|
|
|
|
#'eat--grab-mouse)
|
|
|
|
|
(setf (eat-term-manipulate-selection-function eat--terminal)
|
|
|
|
|
#'eat--manipulate-kill-ring)
|
|
|
|
|
(setf (eat-term-ring-bell-function eat--terminal) #'eat--bell)
|
|
|
|
|
(setf (eat-term-set-cwd-function eat--terminal) #'eat--set-cwd)
|
|
|
|
|
(setf (eat-term-set-cmd-function eat--terminal) #'eat--set-cmd)
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(setf (eat-term-parameter eat--terminal 'eat--process) proc)
|
2023-03-21 20:22:11 +06:00
|
|
|
|
(unless (>= emacs-major-version 29)
|
|
|
|
|
(setf (eat-term-parameter eat--terminal 'eat--input-process)
|
|
|
|
|
proc))
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(setf (eat-term-parameter eat--terminal 'eat--output-process)
|
|
|
|
|
proc)
|
2022-11-28 23:22:52 +06:00
|
|
|
|
(when-let* ((window (get-buffer-window nil t)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(with-selected-window window
|
|
|
|
|
(eat-term-resize eat--terminal (window-max-chars-per-line)
|
2022-12-04 22:49:56 +06:00
|
|
|
|
(floor (window-screen-lines)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat-term-redisplay eat--terminal)
|
2022-12-01 01:40:17 +06:00
|
|
|
|
(setq-local eshell-output-filter-functions
|
|
|
|
|
'(eat--eshell-output-filter))
|
2022-12-11 14:41:38 +06:00
|
|
|
|
(eat--eshell-process-running-mode +1)
|
2022-12-28 21:35:39 +06:00
|
|
|
|
(eat-eshell-semi-char-mode)
|
|
|
|
|
(run-hooks 'eat-eshell-exec-hook)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--eshell-cleanup ()
|
|
|
|
|
"Cleanup everything."
|
|
|
|
|
(when eat--terminal
|
|
|
|
|
(let ((inhibit-read-only t))
|
2022-12-01 01:40:17 +06:00
|
|
|
|
(cd-absolute eat--eshell-invocation-directory)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(goto-char (eat-term-end eat--terminal))
|
|
|
|
|
(unless (or (= (point) (point-min))
|
|
|
|
|
(= (char-before) ?\n))
|
|
|
|
|
(insert ?\n))
|
|
|
|
|
(set-marker eshell-last-output-start (point))
|
|
|
|
|
(set-marker eshell-last-output-end (point))
|
|
|
|
|
(eat--cursor-blink-mode -1)
|
|
|
|
|
(eat--grab-mouse nil nil)
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(set-process-filter (eat-term-parameter
|
|
|
|
|
eat--terminal 'eat--output-process)
|
|
|
|
|
#'eshell-output-filter)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat-term-delete eat--terminal)
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setq eat--terminal nil)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(kill-local-variable 'eshell-output-filter-functions)
|
|
|
|
|
(eat--eshell-semi-char-mode -1)
|
|
|
|
|
(eat--eshell-char-mode -1)
|
2022-12-11 14:41:38 +06:00
|
|
|
|
(eat--eshell-process-running-mode -1)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(setq buffer-read-only nil))))
|
|
|
|
|
|
2022-11-29 00:48:04 +06:00
|
|
|
|
(declare-function eshell-output-filter "esh-mode" (process string))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defun eat--eshell-process-output-queue (process buffer)
|
|
|
|
|
"Process the output queue on BUFFER from PROCESS."
|
|
|
|
|
(when (buffer-live-p buffer)
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(when eat--process-output-queue-timer
|
|
|
|
|
(cancel-timer eat--process-output-queue-timer))
|
|
|
|
|
(setq eat--output-queue-first-chunk-time nil)
|
|
|
|
|
(let ((queue eat--pending-output-chunks))
|
|
|
|
|
(setq eat--pending-output-chunks nil)
|
|
|
|
|
(combine-change-calls
|
|
|
|
|
(eat-term-beginning eat--terminal)
|
|
|
|
|
(eat-term-end eat--terminal)
|
|
|
|
|
;; TODO: Is `string-join' OK or should we use a loop?
|
|
|
|
|
(eshell-output-filter
|
|
|
|
|
process (string-join (nreverse queue))))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--eshell-filter (process string)
|
|
|
|
|
"Process output STRING from PROCESS."
|
|
|
|
|
(when (buffer-live-p (process-buffer process))
|
|
|
|
|
(with-current-buffer (process-buffer process)
|
|
|
|
|
(when eat--process-output-queue-timer
|
|
|
|
|
(cancel-timer eat--process-output-queue-timer))
|
|
|
|
|
(unless eat--output-queue-first-chunk-time
|
|
|
|
|
(setq eat--output-queue-first-chunk-time (current-time)))
|
|
|
|
|
(push string eat--pending-output-chunks)
|
|
|
|
|
(let ((time-left
|
|
|
|
|
(- eat-maximum-latency
|
|
|
|
|
(float-time
|
|
|
|
|
(time-subtract
|
|
|
|
|
nil eat--output-queue-first-chunk-time)))))
|
|
|
|
|
(if (<= time-left 0)
|
|
|
|
|
(eat--eshell-process-output-queue
|
|
|
|
|
process (current-buffer))
|
|
|
|
|
(setq eat--process-output-queue-timer
|
|
|
|
|
(run-with-timer
|
|
|
|
|
(min time-left eat-minimum-latency) nil
|
|
|
|
|
#'eat--eshell-process-output-queue process
|
|
|
|
|
(current-buffer))))))))
|
|
|
|
|
|
2022-11-29 00:48:04 +06:00
|
|
|
|
(declare-function eshell-sentinel "esh-proc" (proc string))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defun eat--eshell-sentinel (process message)
|
|
|
|
|
"Process status message MESSAGE from PROCESS."
|
|
|
|
|
(when (buffer-live-p (process-buffer process))
|
|
|
|
|
(with-current-buffer (process-buffer process)
|
|
|
|
|
(cl-letf* ((process-send-string
|
|
|
|
|
(symbol-function #'process-send-string))
|
|
|
|
|
((symbol-function #'process-send-string)
|
|
|
|
|
(lambda (proc string)
|
|
|
|
|
(when (or (not (eq proc process))
|
|
|
|
|
(process-live-p proc))
|
|
|
|
|
(funcall process-send-string proc string)))))
|
|
|
|
|
(eat--eshell-process-output-queue process (current-buffer)))
|
|
|
|
|
(when (memq (process-status process) '(signal exit))
|
|
|
|
|
(eat--eshell-cleanup))))
|
|
|
|
|
(eshell-sentinel process message))
|
|
|
|
|
|
2022-12-14 14:12:34 +06:00
|
|
|
|
(declare-function eshell-search-path "esh-ext" (name))
|
2022-12-15 18:57:55 +06:00
|
|
|
|
(declare-function eshell-interactive-output-p "esh-io"
|
|
|
|
|
(&optional index handles))
|
2022-12-12 10:22:14 +06:00
|
|
|
|
(defvar eshell-current-subjob-p) ; In `esh-proc'.
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; HACK: This is a dirty hack, it can break easily.
|
|
|
|
|
(defun eat--eshell-adjust-make-process-args (fn command args)
|
|
|
|
|
"Setup an environment to adjust `make-process' arguments.
|
|
|
|
|
|
|
|
|
|
Call FN with COMMAND and ARGS, and whenever `make-process' is called,
|
|
|
|
|
modify its argument to change the filter, the sentinel and invoke
|
|
|
|
|
`stty' from the new process."
|
2022-12-14 14:12:34 +06:00
|
|
|
|
(if (or eshell-current-subjob-p
|
2022-12-15 18:57:55 +06:00
|
|
|
|
(not (eshell-interactive-output-p))
|
2022-12-14 14:12:34 +06:00
|
|
|
|
(and (not (eshell-search-path "stty"))
|
|
|
|
|
(pcase eat-eshell-fallback-if-stty-not-available
|
|
|
|
|
('nil nil)
|
|
|
|
|
('t t)
|
|
|
|
|
('ask (not (y-or-n-p "The program stty can't be \
|
|
|
|
|
found, input won't be shown if terminal emulation is enabled. \
|
|
|
|
|
Disable terminal emulation?")))
|
|
|
|
|
((and (pred functionp) function)
|
|
|
|
|
(apply function command args)))))
|
2022-12-12 10:22:14 +06:00
|
|
|
|
(funcall fn command args)
|
2022-12-14 14:32:03 +06:00
|
|
|
|
(let ((hook (lambda (proc)
|
|
|
|
|
(set-process-filter proc #'eat--eshell-filter)
|
|
|
|
|
(set-process-sentinel proc #'eat--eshell-sentinel)
|
|
|
|
|
(eat--eshell-setup-proc-and-term proc))))
|
2022-12-15 13:00:06 +06:00
|
|
|
|
(add-hook 'eshell-exec-hook hook 99)
|
2022-12-14 14:32:03 +06:00
|
|
|
|
(unwind-protect
|
2022-12-15 13:00:06 +06:00
|
|
|
|
(cond
|
|
|
|
|
;; Emacs 29 and above.
|
|
|
|
|
((>= emacs-major-version 29)
|
|
|
|
|
(cl-letf*
|
|
|
|
|
((make-process (symbol-function #'make-process))
|
|
|
|
|
((symbol-function #'make-process)
|
|
|
|
|
(lambda (&rest plist)
|
|
|
|
|
;; Make sure we don't attack wrong process.
|
|
|
|
|
(if (not (equal
|
|
|
|
|
(plist-get plist :command)
|
|
|
|
|
(cons (file-local-name
|
|
|
|
|
(expand-file-name command))
|
|
|
|
|
args)))
|
|
|
|
|
(apply make-process plist)
|
|
|
|
|
(setf (plist-get plist :command)
|
|
|
|
|
`("/usr/bin/env" "sh" "-c"
|
|
|
|
|
,(format "stty -nl echo rows %d columns\
|
|
|
|
|
%d sane 2>%s ; if [ $1 = .. ]; then shift; fi; exec \"$@\""
|
|
|
|
|
(floor (window-screen-lines))
|
|
|
|
|
(window-max-chars-per-line)
|
|
|
|
|
null-device)
|
|
|
|
|
".." ,@(plist-get plist :command)))
|
|
|
|
|
(apply make-process plist)))))
|
|
|
|
|
(funcall fn command args)))
|
|
|
|
|
;; Emacs 28.
|
|
|
|
|
(t
|
|
|
|
|
(cl-letf*
|
|
|
|
|
((start-file-process
|
|
|
|
|
(symbol-function #'start-file-process))
|
|
|
|
|
((symbol-function #'start-file-process)
|
|
|
|
|
(lambda (name buffer &rest command)
|
|
|
|
|
(apply start-file-process name buffer
|
|
|
|
|
"/usr/bin/env" "sh" "-c"
|
|
|
|
|
(format "stty -nl echo rows %d columns %d \
|
|
|
|
|
sane 2>%s ; if [ $1 = .. ]; then shift; fi; exec \"$@\""
|
|
|
|
|
(floor (window-screen-lines))
|
|
|
|
|
(window-max-chars-per-line)
|
|
|
|
|
null-device)
|
|
|
|
|
".." command))))
|
|
|
|
|
(funcall fn command args))))
|
2022-12-14 14:32:03 +06:00
|
|
|
|
(remove-hook 'eshell-exec-hook hook)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(defun eat--eshell-set-input-process ()
|
|
|
|
|
"Set the process that gets user input."
|
|
|
|
|
(when eat--terminal
|
|
|
|
|
(setf (eat-term-parameter eat--terminal 'eat--input-process)
|
|
|
|
|
(eshell-head-process))))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
;;;;; Minor Modes.
|
|
|
|
|
|
2022-12-12 14:00:57 +06:00
|
|
|
|
(defun eat--eshell-synchronize-scroll (windows)
|
|
|
|
|
"Synchronize scrolling and point between terminal and WINDOWS.
|
|
|
|
|
|
|
|
|
|
WINDOWS is a list of windows. WINDOWS may also contain the special
|
|
|
|
|
symbol `buffer', in which case the point of current buffer is set."
|
|
|
|
|
(dolist (window windows)
|
|
|
|
|
(if (eq window 'buffer)
|
|
|
|
|
(goto-char (eat-term-display-cursor eat--terminal))
|
|
|
|
|
(set-window-start
|
|
|
|
|
window
|
|
|
|
|
(if (or (eat-term-in-alternative-display-p eat--terminal)
|
|
|
|
|
eat--eshell-char-mode)
|
|
|
|
|
(eat-term-display-beginning eat--terminal)
|
|
|
|
|
(save-restriction
|
|
|
|
|
(narrow-to-region
|
|
|
|
|
(eat-term-beginning eat--terminal)
|
|
|
|
|
(eat-term-end eat--terminal))
|
|
|
|
|
(let ((start-line (- (floor (window-screen-lines))
|
|
|
|
|
(line-number-at-pos (point-max)))))
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(widen)
|
|
|
|
|
(if (<= start-line 0)
|
|
|
|
|
(eat-term-display-beginning eat--terminal)
|
|
|
|
|
(vertical-motion (- start-line))
|
|
|
|
|
(point))))))
|
|
|
|
|
(set-window-point
|
|
|
|
|
window (eat-term-display-cursor eat--terminal)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
2022-12-08 17:00:12 +06:00
|
|
|
|
(defun eat--eshell-update-cwd ()
|
|
|
|
|
"Update the current working directory."
|
|
|
|
|
(setq eat--eshell-invocation-directory default-directory))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(define-minor-mode eat--eshell-local-mode
|
|
|
|
|
"Toggle Eat terminal emulation is Eshell."
|
|
|
|
|
:interactive nil
|
2022-11-29 00:58:09 +06:00
|
|
|
|
(let ((locals '(cursor-type
|
|
|
|
|
glyphless-char-display
|
|
|
|
|
track-mouse
|
|
|
|
|
filter-buffer-substring-function
|
|
|
|
|
eat--terminal
|
|
|
|
|
eat--synchronize-scroll-function
|
|
|
|
|
eat--mouse-grabbing-type
|
|
|
|
|
eat--pending-output-chunks
|
|
|
|
|
eat--output-queue-first-chunk-time
|
2022-12-01 01:40:17 +06:00
|
|
|
|
eat--process-output-queue-timer
|
|
|
|
|
eat--eshell-invocation-directory)))
|
2022-11-29 00:58:09 +06:00
|
|
|
|
(cond
|
|
|
|
|
(eat--eshell-local-mode
|
|
|
|
|
(mapc #'make-local-variable locals)
|
|
|
|
|
(setq eat--synchronize-scroll-function
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
#'eat--eshell-synchronize-scroll)
|
|
|
|
|
(setq filter-buffer-substring-function
|
2022-11-29 00:58:09 +06:00
|
|
|
|
#'eat--filter-buffer-substring)
|
|
|
|
|
;; Make sure glyphless character don't display a huge box glyph,
|
|
|
|
|
;; that would break the display.
|
|
|
|
|
(eat--setup-glyphless-chars)
|
2022-12-11 00:20:05 +06:00
|
|
|
|
(eat--eshell-update-cwd)
|
2022-11-29 00:58:09 +06:00
|
|
|
|
(when eat-enable-blinking-text
|
|
|
|
|
(eat-blink-mode +1)))
|
|
|
|
|
(t
|
|
|
|
|
(when eat-enable-blinking-text
|
|
|
|
|
(eat-blink-mode -1))
|
|
|
|
|
(mapc #'kill-local-variable locals)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
2022-11-29 00:48:04 +06:00
|
|
|
|
(declare-function eshell-gather-process-output "esh-proc"
|
|
|
|
|
(command args))
|
|
|
|
|
(defvar eshell-variable-aliases-list) ; In `esh-var'.
|
2022-11-30 12:29:05 +06:00
|
|
|
|
(defvar eshell-last-async-proc) ; In `esh-cmd'.
|
2022-11-29 00:48:04 +06:00
|
|
|
|
(defvar eshell-last-async-procs) ; In `esh-cmd'.
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;;;###autoload
|
|
|
|
|
(define-minor-mode eat-eshell-mode
|
2022-12-19 11:31:56 +06:00
|
|
|
|
"Toggle Eat terminal emulation in Eshell."
|
2022-09-02 20:03:33 +06:00
|
|
|
|
:global t
|
|
|
|
|
:lighter (eat--eshell-local-mode
|
|
|
|
|
(" Eat-Eshell"
|
|
|
|
|
(:eval
|
|
|
|
|
(when eat--terminal
|
|
|
|
|
(cond
|
|
|
|
|
(eat--eshell-semi-char-mode
|
|
|
|
|
`("["
|
|
|
|
|
(:propertize
|
|
|
|
|
"semi-char"
|
|
|
|
|
help-echo
|
|
|
|
|
,(concat "mouse-1: Switch to char mode, "
|
|
|
|
|
"mouse-3: Switch to emacs mode")
|
|
|
|
|
mouse-face mode-line-highlight
|
|
|
|
|
local-map
|
|
|
|
|
(keymap
|
|
|
|
|
(mode-line
|
|
|
|
|
. (keymap
|
|
|
|
|
(down-mouse-1 . eat-eshell-char-mode)
|
|
|
|
|
(down-mouse-3 . eat-eshell-emacs-mode)))))
|
|
|
|
|
"]"))
|
|
|
|
|
(eat--eshell-char-mode
|
|
|
|
|
'("["
|
|
|
|
|
(:propertize
|
|
|
|
|
"char"
|
|
|
|
|
help-echo
|
|
|
|
|
,(concat "mouse-1: Switch to semi-char mode, "
|
|
|
|
|
"mouse-3: Switch to emacs mode")
|
|
|
|
|
mouse-face mode-line-highlight
|
|
|
|
|
local-map
|
|
|
|
|
(keymap
|
|
|
|
|
(mode-line
|
|
|
|
|
. (keymap
|
|
|
|
|
(down-mouse-1 . eat-eshell-semi-char-mode)
|
|
|
|
|
(down-mouse-3 . eat-eshell-emacs-mode)))))
|
|
|
|
|
"]"))
|
|
|
|
|
(t
|
|
|
|
|
`("["
|
|
|
|
|
(:propertize
|
|
|
|
|
"emacs"
|
|
|
|
|
help-echo
|
|
|
|
|
,(concat "mouse-1: Switch to semi-char mode, "
|
|
|
|
|
"mouse-3: Switch to char mode")
|
|
|
|
|
mouse-face mode-line-highlight
|
|
|
|
|
local-map
|
|
|
|
|
(keymap
|
|
|
|
|
(mode-line
|
|
|
|
|
. (keymap
|
|
|
|
|
(down-mouse-1 . eat-eshell-semi-char-mode)
|
|
|
|
|
(down-mouse-3 . eat-eshell-char-mode)))))
|
|
|
|
|
"]")))))))
|
2023-03-09 11:36:14 +06:00
|
|
|
|
:group 'eat-eshell
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(cond
|
|
|
|
|
(eat-eshell-mode
|
|
|
|
|
(let ((buffers nil))
|
|
|
|
|
(setq eat-eshell-mode nil)
|
|
|
|
|
(require 'esh-mode)
|
|
|
|
|
(require 'esh-proc)
|
|
|
|
|
(require 'esh-var)
|
|
|
|
|
(require 'esh-cmd)
|
|
|
|
|
(dolist (buffer (buffer-list))
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(when (eq major-mode #'eshell-mode)
|
2022-11-30 12:29:05 +06:00
|
|
|
|
(when (if (< emacs-major-version 29)
|
|
|
|
|
(bound-and-true-p eshell-last-async-proc)
|
|
|
|
|
(bound-and-true-p eshell-last-async-procs))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(user-error
|
|
|
|
|
(concat "Can't toggle Eat Eshell mode while"
|
|
|
|
|
" any Eshell process is running")))
|
|
|
|
|
(push buffer buffers))))
|
|
|
|
|
(setq eat-eshell-mode t)
|
|
|
|
|
(dolist (buffer buffers)
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(eat--eshell-local-mode +1))))
|
|
|
|
|
(add-hook 'eshell-mode-hook #'eat--eshell-local-mode)
|
2022-12-08 17:00:12 +06:00
|
|
|
|
(add-hook 'eshell-directory-change-hook #'eat--eshell-update-cwd)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(setq eshell-variable-aliases-list
|
2022-11-30 12:29:05 +06:00
|
|
|
|
`(("TERM" eat--eshell-term-name t)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
("TERMINFO" eat-term-terminfo-directory t)
|
|
|
|
|
("INSIDE_EMACS" eat-term-inside-emacs t)
|
2022-12-03 11:14:01 +06:00
|
|
|
|
("EAT_SHELL_INTEGRATION_DIR"
|
|
|
|
|
eat-term-shell-integration-directory t)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
,@eshell-variable-aliases-list))
|
|
|
|
|
(advice-add #'eshell-gather-process-output :around
|
2023-03-20 23:54:33 +06:00
|
|
|
|
#'eat--eshell-adjust-make-process-args)
|
2023-03-21 20:22:11 +06:00
|
|
|
|
(when (>= emacs-major-version 29)
|
|
|
|
|
(advice-add #'eshell-resume-eval :after
|
|
|
|
|
#'eat--eshell-set-input-process)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(t
|
|
|
|
|
(let ((buffers nil))
|
|
|
|
|
(setq eat-eshell-mode t)
|
|
|
|
|
(dolist (buffer (buffer-list))
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(when (and (eq major-mode #'eshell-mode)
|
|
|
|
|
eat--eshell-local-mode)
|
2022-11-30 12:29:05 +06:00
|
|
|
|
(when (if (< emacs-major-version 29)
|
|
|
|
|
(bound-and-true-p eshell-last-async-proc)
|
|
|
|
|
(bound-and-true-p eshell-last-async-procs))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(user-error
|
|
|
|
|
(concat "Can't toggle Eat Eshell mode while"
|
|
|
|
|
" any Eshell process is running")))
|
|
|
|
|
(push buffer buffers))))
|
|
|
|
|
(setq eat-eshell-mode nil)
|
|
|
|
|
(dolist (buffer buffers)
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(eat--eshell-local-mode -1))))
|
|
|
|
|
(remove-hook 'eshell-mode-hook #'eat--eshell-local-mode)
|
2022-12-08 17:00:12 +06:00
|
|
|
|
(remove-hook 'eshell-directory-change-hook
|
|
|
|
|
#'eat--eshell-update-cwd)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(setq eshell-variable-aliases-list
|
|
|
|
|
(cl-delete-if
|
|
|
|
|
(lambda (elem)
|
|
|
|
|
(member elem
|
2022-11-30 12:29:05 +06:00
|
|
|
|
'(("TERM" eat--eshell-term-name t)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
("TERMINFO" eat-term-terminfo-directory t)
|
|
|
|
|
("INSIDE_EMACS" eat-term-inside-emacs t))))
|
|
|
|
|
eshell-variable-aliases-list))
|
|
|
|
|
(advice-remove #'eshell-gather-process-output
|
2023-03-20 23:54:33 +06:00
|
|
|
|
#'eat--eshell-adjust-make-process-args)
|
2023-03-21 20:22:11 +06:00
|
|
|
|
(when (>= emacs-major-version 29)
|
|
|
|
|
(advice-remove #'eshell-resume-eval
|
|
|
|
|
#'eat--eshell-set-input-process)))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;; Eshell Visual Command Handling.
|
|
|
|
|
|
2022-11-29 00:48:04 +06:00
|
|
|
|
(defvar eshell-destroy-buffer-when-process-dies) ; In `em-term'.
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;; Adapted from `em-term'.
|
|
|
|
|
(defun eat--eshell-visual-sentinel (proc _msg)
|
|
|
|
|
"Clean up the buffer visiting PROC.
|
|
|
|
|
|
|
|
|
|
If `eshell-destroy-buffer-when-process-dies' is non-nil, destroy
|
|
|
|
|
the buffer.
|
|
|
|
|
|
|
|
|
|
MSG describes PROC's status."
|
|
|
|
|
(when eshell-destroy-buffer-when-process-dies
|
|
|
|
|
(let ((proc-buf (process-buffer proc)))
|
|
|
|
|
(when (and proc-buf (buffer-live-p proc-buf)
|
|
|
|
|
(not (eq 'run (process-status proc)))
|
|
|
|
|
(= (process-exit-status proc) 0))
|
|
|
|
|
(if (eq (current-buffer) proc-buf)
|
2022-11-28 23:22:52 +06:00
|
|
|
|
(when-let* ((buf (and (boundp 'eshell-parent-buffer)
|
|
|
|
|
(buffer-live-p eshell-parent-buffer)
|
|
|
|
|
eshell-parent-buffer)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(switch-to-buffer buf)))
|
|
|
|
|
(kill-buffer proc-buf)))))
|
|
|
|
|
|
2022-11-29 00:48:04 +06:00
|
|
|
|
(defvar eshell-interpreter-alist) ; In `esh-ext'.
|
|
|
|
|
(declare-function eshell-find-interpreter "esh-ext"
|
|
|
|
|
(file args &optional no-examine-p))
|
|
|
|
|
(declare-function eshell-stringify-list "esh-util" (args))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(defun eat--eshell-exec-visual (&rest args)
|
|
|
|
|
"Run the specified PROGRAM in a terminal emulation buffer.
|
|
|
|
|
|
|
|
|
|
ARGS are passed to the program. At the moment, no piping of input is
|
|
|
|
|
allowed."
|
|
|
|
|
(require 'esh-ext)
|
|
|
|
|
(require 'esh-util)
|
2022-11-28 12:40:19 +06:00
|
|
|
|
(let* ((eshell-interpreter-alist nil)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(interp (eshell-find-interpreter (car args) (cdr args)))
|
|
|
|
|
(program (car interp))
|
|
|
|
|
(args (flatten-tree
|
|
|
|
|
(eshell-stringify-list (append (cdr interp)
|
|
|
|
|
(cdr args)))))
|
|
|
|
|
(eat-buf
|
|
|
|
|
(generate-new-buffer
|
|
|
|
|
(concat "*" (file-name-nondirectory program) "*")))
|
|
|
|
|
(eshell-buf (current-buffer)))
|
|
|
|
|
(with-current-buffer eat-buf
|
|
|
|
|
(switch-to-buffer eat-buf)
|
|
|
|
|
(eat-mode)
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setq-local eshell-parent-buffer eshell-buf)
|
|
|
|
|
(setq-local eat-kill-buffer-on-exit nil)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat-exec eat-buf program program nil args)
|
|
|
|
|
(let ((proc (get-buffer-process eat-buf)))
|
|
|
|
|
(if (and proc (eq 'run (process-status proc)))
|
|
|
|
|
(let ((sentinel (process-sentinel proc)))
|
|
|
|
|
(add-function :after (var sentinel)
|
|
|
|
|
#'eat--eshell-visual-sentinel)
|
|
|
|
|
(set-process-sentinel proc sentinel))
|
|
|
|
|
(error "Failed to invoke visual command")))
|
|
|
|
|
(eat-semi-char-mode)))
|
|
|
|
|
nil)
|
|
|
|
|
|
2022-11-29 00:48:04 +06:00
|
|
|
|
(declare-function eshell-exec-visual "em-term" (&rest args))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;;;###autoload
|
|
|
|
|
(define-minor-mode eat-eshell-visual-command-mode
|
|
|
|
|
"Toggle running Eshell visual commands with Eat."
|
|
|
|
|
:group 'eat-eshell
|
|
|
|
|
:global t
|
|
|
|
|
(if eat-eshell-visual-command-mode
|
|
|
|
|
(advice-add #'eshell-exec-visual :override
|
|
|
|
|
#'eat--eshell-exec-visual)
|
|
|
|
|
(advice-remove #'eshell-exec-visual #'eat--eshell-exec-visual)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;; Project Integration.
|
|
|
|
|
|
2022-11-29 00:48:04 +06:00
|
|
|
|
(declare-function project-root "project" (project))
|
|
|
|
|
(declare-function project-prefixed-buffer-name "project" (mode))
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun eat-project (&optional arg)
|
|
|
|
|
"Start Eat in the current project's root directory.
|
|
|
|
|
|
|
|
|
|
Start a new Eat session, or switch to an already active session.
|
|
|
|
|
Return the buffer selected (or created).
|
|
|
|
|
|
|
|
|
|
With a non-numeric prefix ARG, create a new session.
|
|
|
|
|
|
2023-03-29 23:09:30 +06:00
|
|
|
|
With a numeric prefix ARG (like
|
|
|
|
|
\\[universal-argument] 42 \\[eat-project]), switch to the session with
|
|
|
|
|
that number, or create it if it doesn't already exist."
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(interactive "P")
|
|
|
|
|
(require 'project)
|
|
|
|
|
(let* ((default-directory (project-root (project-current t)))
|
|
|
|
|
(eat-buffer-name (project-prefixed-buffer-name "eat")))
|
|
|
|
|
(eat nil arg)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;; Tracing.
|
|
|
|
|
|
|
|
|
|
;;;;; Recording Trace Data.
|
|
|
|
|
|
|
|
|
|
(defconst eat--trace-recorded-variables
|
|
|
|
|
'(eat-term-scrollback-size
|
|
|
|
|
eat-enable-alternative-display)
|
|
|
|
|
"The variable to record in trace output.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--trace-output-buffer nil
|
|
|
|
|
"Buffer where the trace data is written to.")
|
|
|
|
|
|
|
|
|
|
(defun eat--trace-log (time operation &rest args)
|
|
|
|
|
"Log TIME, OPERATION and ARGS into trace output.
|
|
|
|
|
|
|
|
|
|
TIME defaults to the current time.
|
|
|
|
|
|
|
|
|
|
The current buffer should be the trace output buffer. Move the point
|
|
|
|
|
to the end of (accessible portion of) buffer."
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
;; Hope that `float-time' won't roll over while tracing. ;-)
|
|
|
|
|
(insert (replace-regexp-in-string
|
2022-12-07 15:34:14 +06:00
|
|
|
|
(rx (any (0 . 31)))
|
|
|
|
|
(lambda (string) (format "\\\\x%02x" (aref string 0)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(format "%S" `(,(float-time time) ,operation ,@args)))
|
|
|
|
|
?\n))
|
|
|
|
|
|
|
|
|
|
(defun eat--trace-stop ()
|
|
|
|
|
"Stop tracing the terminal in current buffer."
|
|
|
|
|
(when eat--trace-output-buffer
|
|
|
|
|
(with-current-buffer eat--trace-output-buffer
|
|
|
|
|
(eat--trace-log nil 'finish)))
|
|
|
|
|
(remove-hook 'kill-buffer-hook #'eat--trace-stop t)
|
|
|
|
|
(kill-local-variable 'eat--trace-output-buffer))
|
|
|
|
|
|
|
|
|
|
(defun eat--trace-exec (fn buffer name command startfile switches)
|
|
|
|
|
"Trace `eat-exec'.
|
|
|
|
|
|
|
|
|
|
BUFFER is the buffer and COMMAND and SWITCHES are the invocation
|
|
|
|
|
command. BUFFER, NAME, COMMAND, STARTFILE and SWITCHES are passed to
|
|
|
|
|
FN, `eat-exec', which see."
|
|
|
|
|
(let ((time (current-time)))
|
|
|
|
|
(prog1
|
|
|
|
|
(funcall fn buffer name command startfile switches)
|
|
|
|
|
(let ((buf (generate-new-buffer
|
|
|
|
|
(format "*eat-trace %s*: %s"
|
|
|
|
|
(buffer-name buffer)
|
|
|
|
|
(mapconcat #'shell-quote-argument
|
|
|
|
|
(cons command switches) " "))))
|
|
|
|
|
(width nil)
|
|
|
|
|
(height nil)
|
|
|
|
|
(variables nil))
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(setq-local eat--trace-output-buffer buf)
|
|
|
|
|
(add-hook 'kill-buffer-hook #'eat--trace-stop nil t)
|
|
|
|
|
(let ((size (eat-term-size eat--terminal)))
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setq width (car size))
|
|
|
|
|
(setq height (cdr size)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(dolist (var eat--trace-recorded-variables)
|
|
|
|
|
(push (cons var (symbol-value var)) variables)))
|
|
|
|
|
(with-current-buffer buf
|
|
|
|
|
(lisp-data-mode)
|
2022-11-29 00:18:28 +06:00
|
|
|
|
(insert ";; -*- mode: lisp-data -*-\n")
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat--trace-log time 'create 'eat width height
|
|
|
|
|
variables))))))
|
|
|
|
|
|
|
|
|
|
(defun eat--trace-process-output-queue (fn buffer)
|
|
|
|
|
"Trace `eat--process-output-queue'.
|
|
|
|
|
|
|
|
|
|
BUFFER is passed to FN, `eat--process-output-queue', which see."
|
|
|
|
|
(if (or (not (buffer-live-p buffer))
|
|
|
|
|
(not (buffer-local-value 'eat--trace-output-buffer buffer)))
|
|
|
|
|
(funcall fn buffer)
|
|
|
|
|
(cl-letf* ((eat-term-process-output
|
|
|
|
|
(symbol-function #'eat-term-process-output))
|
|
|
|
|
((symbol-function #'eat-term-process-output)
|
|
|
|
|
(lambda (terminal output)
|
|
|
|
|
(when (buffer-live-p eat--trace-output-buffer)
|
|
|
|
|
(with-current-buffer eat--trace-output-buffer
|
|
|
|
|
(eat--trace-log nil 'output output)))
|
|
|
|
|
(funcall eat-term-process-output terminal output)))
|
|
|
|
|
(eat-term-redisplay
|
|
|
|
|
(symbol-function #'eat-term-redisplay))
|
|
|
|
|
((symbol-function #'eat-term-redisplay)
|
|
|
|
|
(lambda (terminal)
|
|
|
|
|
(when (buffer-live-p eat--trace-output-buffer)
|
|
|
|
|
(with-current-buffer eat--trace-output-buffer
|
|
|
|
|
(eat--trace-log nil 'redisplay)))
|
|
|
|
|
(funcall eat-term-redisplay terminal))))
|
|
|
|
|
(funcall fn buffer))))
|
|
|
|
|
|
|
|
|
|
(defun eat--trace-adjust-process-window-size (fn process windows)
|
|
|
|
|
"Trace `eat--adjust-process-window-size'.
|
|
|
|
|
|
|
|
|
|
PROCESS and WINDOWS are passed to FN,
|
|
|
|
|
`eat--adjust-process-window-size', which see."
|
|
|
|
|
(cl-letf*
|
|
|
|
|
((eat-term-resize (symbol-function #'eat-term-resize))
|
|
|
|
|
((symbol-function #'eat-term-resize)
|
|
|
|
|
(lambda (terminal width height)
|
|
|
|
|
(when (buffer-live-p eat--trace-output-buffer)
|
|
|
|
|
(with-current-buffer eat--trace-output-buffer
|
|
|
|
|
(eat--trace-log nil 'resize width height)))
|
|
|
|
|
(funcall eat-term-resize terminal width height)))
|
|
|
|
|
(eat-term-redisplay (symbol-function #'eat-term-redisplay))
|
|
|
|
|
((symbol-function #'eat-term-redisplay)
|
|
|
|
|
(lambda (terminal)
|
|
|
|
|
(when (buffer-live-p eat--trace-output-buffer)
|
|
|
|
|
(with-current-buffer eat--trace-output-buffer
|
|
|
|
|
(eat--trace-log nil 'redisplay)))
|
|
|
|
|
(funcall eat-term-redisplay terminal))))
|
|
|
|
|
(funcall fn process windows)))
|
|
|
|
|
|
|
|
|
|
(defun eat--trace-sentinel (fn &rest args)
|
|
|
|
|
"Trace `eat--sentinel'.
|
|
|
|
|
|
|
|
|
|
Elements of ARGS are passed to FN, `eat--sentinel', which see."
|
|
|
|
|
(cl-letf* ((eat-term-delete (symbol-function #'eat-term-delete))
|
|
|
|
|
((symbol-function #'eat-term-delete)
|
|
|
|
|
(lambda (terminal)
|
|
|
|
|
(when (buffer-live-p eat--trace-output-buffer)
|
|
|
|
|
(eat--trace-stop))
|
|
|
|
|
(funcall eat-term-delete terminal))))
|
|
|
|
|
(apply fn args)))
|
|
|
|
|
|
|
|
|
|
(defun eat--trace-reset (fn)
|
|
|
|
|
"Trace `eat-reset'.
|
|
|
|
|
|
|
|
|
|
FN is original definition of `eat-reset'."
|
|
|
|
|
(cl-letf*
|
|
|
|
|
((eat-term-reset (symbol-function #'eat-term-reset))
|
|
|
|
|
((symbol-function #'eat-term-reset)
|
|
|
|
|
(lambda (terminal)
|
|
|
|
|
(when (buffer-live-p eat--trace-output-buffer)
|
|
|
|
|
(with-current-buffer eat--trace-output-buffer
|
|
|
|
|
(eat--trace-log nil 'reset)))
|
|
|
|
|
(funcall eat-term-reset terminal)))
|
|
|
|
|
(eat-term-redisplay (symbol-function #'eat-term-redisplay))
|
|
|
|
|
((symbol-function #'eat-term-redisplay)
|
|
|
|
|
(lambda (terminal)
|
|
|
|
|
(when (buffer-live-p eat--trace-output-buffer)
|
|
|
|
|
(with-current-buffer eat--trace-output-buffer
|
|
|
|
|
(eat--trace-log nil 'redisplay)))
|
|
|
|
|
(funcall eat-term-redisplay terminal))))
|
|
|
|
|
(funcall fn)))
|
|
|
|
|
|
2022-12-03 11:18:28 +06:00
|
|
|
|
(defun eat--trace-eshell-adjust-make-process-args (fn &rest args)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
"Trace `eat--eshell-adjust-make-process-args'.
|
|
|
|
|
|
|
|
|
|
ARGS is passed to FN, `eat--eshell-adjust-make-process-args', which
|
|
|
|
|
see."
|
|
|
|
|
(cl-letf*
|
|
|
|
|
((command nil)
|
|
|
|
|
(make-process (symbol-function #'make-process))
|
|
|
|
|
((symbol-function #'make-process)
|
|
|
|
|
(lambda (&rest plist)
|
|
|
|
|
(prog1
|
|
|
|
|
(apply make-process plist)
|
|
|
|
|
(setq command (nthcdr 5 (plist-get plist :command))))))
|
|
|
|
|
(eat--eshell-setup-proc-and-term
|
|
|
|
|
(symbol-function #'eat--eshell-setup-proc-and-term))
|
|
|
|
|
((symbol-function #'eat--eshell-setup-proc-and-term)
|
|
|
|
|
(lambda (proc)
|
|
|
|
|
(let ((time (current-time)))
|
|
|
|
|
(prog1
|
|
|
|
|
(funcall eat--eshell-setup-proc-and-term proc)
|
2023-03-20 23:54:33 +06:00
|
|
|
|
(when (eq (eat-term-parameter
|
|
|
|
|
eat--terminal 'eat--output-process)
|
|
|
|
|
proc)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(let ((buf (generate-new-buffer
|
|
|
|
|
(format "*eat-trace %s*: %s"
|
|
|
|
|
(buffer-name)
|
|
|
|
|
(mapconcat
|
|
|
|
|
#'shell-quote-argument
|
|
|
|
|
command " "))))
|
|
|
|
|
(width nil)
|
|
|
|
|
(height nil)
|
|
|
|
|
(variables nil))
|
|
|
|
|
(setq-local eat--trace-output-buffer buf)
|
|
|
|
|
(add-hook 'kill-buffer-hook #'eat--trace-stop nil t)
|
|
|
|
|
(let ((size (eat-term-size eat--terminal)))
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setq width (car size))
|
|
|
|
|
(setq height (cdr size)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(dolist (var eat--trace-recorded-variables)
|
|
|
|
|
(push (cons var (symbol-value var)) variables))
|
|
|
|
|
(with-current-buffer buf
|
|
|
|
|
(lisp-data-mode)
|
|
|
|
|
(insert ";; -*- lisp-data -*-\n")
|
|
|
|
|
(eat--trace-log time 'create 'eshell width height
|
|
|
|
|
variables)))))))))
|
|
|
|
|
(apply fn args)))
|
|
|
|
|
|
2022-12-03 11:18:28 +06:00
|
|
|
|
(defun eat--trace-eshell-output-filter (fn)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
"Trace `eat--eshell-output-filter'.
|
|
|
|
|
|
|
|
|
|
FN is the original definition of `eat--eshell-output-filter', which
|
|
|
|
|
see."
|
|
|
|
|
(if (not (buffer-live-p eat--trace-output-buffer))
|
|
|
|
|
(funcall fn)
|
|
|
|
|
(cl-letf* ((eat-term-process-output
|
|
|
|
|
(symbol-function #'eat-term-process-output))
|
|
|
|
|
((symbol-function #'eat-term-process-output)
|
|
|
|
|
(lambda (terminal output)
|
|
|
|
|
(with-current-buffer eat--trace-output-buffer
|
|
|
|
|
(eat--trace-log nil 'output output))
|
|
|
|
|
(funcall eat-term-process-output terminal output)))
|
|
|
|
|
(eat-term-redisplay
|
|
|
|
|
(symbol-function #'eat-term-redisplay))
|
|
|
|
|
((symbol-function #'eat-term-redisplay)
|
|
|
|
|
(lambda (terminal)
|
|
|
|
|
(with-current-buffer eat--trace-output-buffer
|
|
|
|
|
(eat--trace-log nil 'redisplay))
|
|
|
|
|
(funcall eat-term-redisplay terminal))))
|
|
|
|
|
(funcall fn))))
|
|
|
|
|
|
2022-12-03 11:18:28 +06:00
|
|
|
|
(defun eat--trace-eshell-cleanup (fn)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
"Trace `eat--eshell-cleanup'.
|
|
|
|
|
|
|
|
|
|
FN is the original definition of `eat--eshell-cleanup', which see."
|
|
|
|
|
(if (not (buffer-live-p eat--trace-output-buffer))
|
|
|
|
|
(funcall fn)
|
|
|
|
|
(cl-letf* ((eat-term-delete (symbol-function #'eat-term-delete))
|
|
|
|
|
((symbol-function #'eat-term-delete)
|
|
|
|
|
(lambda (terminal)
|
|
|
|
|
(eat--trace-stop)
|
|
|
|
|
(funcall eat-term-delete terminal))))
|
|
|
|
|
(funcall fn))))
|
|
|
|
|
|
|
|
|
|
(define-minor-mode eat-trace-mode
|
|
|
|
|
"Toggle tracing Eat terminal."
|
|
|
|
|
:global t
|
|
|
|
|
:require 'eat
|
|
|
|
|
:lighter " Eat-Trace"
|
|
|
|
|
(if eat-trace-mode
|
|
|
|
|
(progn
|
|
|
|
|
(advice-add #'eat-exec :around #'eat--trace-exec)
|
|
|
|
|
(advice-add #'eat--process-output-queue :around
|
|
|
|
|
#'eat--trace-process-output-queue)
|
|
|
|
|
(advice-add #'eat--adjust-process-window-size :around
|
|
|
|
|
#'eat--trace-adjust-process-window-size)
|
|
|
|
|
(advice-add #'eat--sentinel :around #'eat--trace-sentinel)
|
|
|
|
|
(advice-add #'eat-reset :around #'eat--trace-reset)
|
|
|
|
|
(advice-add #'eat--eshell-adjust-make-process-args :around
|
2022-12-03 11:18:28 +06:00
|
|
|
|
#'eat--trace-eshell-adjust-make-process-args)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(advice-add #'eat--eshell-output-filter :around
|
2022-12-03 11:18:28 +06:00
|
|
|
|
#'eat--trace-eshell-output-filter)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(advice-add #'eat--eshell-cleanup :around
|
2022-12-03 11:18:28 +06:00
|
|
|
|
#'eat--trace-eshell-cleanup))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(advice-remove #'eat-exec #'eat--trace-exec)
|
|
|
|
|
(advice-remove #'eat--process-output-queue
|
|
|
|
|
#'eat--trace-process-output-queue)
|
|
|
|
|
(advice-remove #'eat--adjust-process-window-size
|
|
|
|
|
#'eat--trace-adjust-process-window-size)
|
|
|
|
|
(advice-remove #'eat--sentinel #'eat--trace-sentinel)
|
|
|
|
|
(advice-remove #'eat-reset #'eat--trace-reset)
|
|
|
|
|
(advice-remove #'eat--eshell-adjust-make-process-args
|
2022-12-03 11:18:28 +06:00
|
|
|
|
#'eat--trace-eshell-adjust-make-process-args)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(advice-remove #'eat--eshell-output-filter
|
2022-12-03 11:18:28 +06:00
|
|
|
|
#'eat--trace-eshell-output-filter)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(advice-remove #'eat--eshell-cleanup
|
2022-12-03 11:18:28 +06:00
|
|
|
|
#'eat--trace-eshell-cleanup)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(dolist (buffer (buffer-list))
|
|
|
|
|
(when (buffer-local-value 'eat--trace-output-buffer buffer)
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(setq-local eat--trace-output-buffer nil))))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;;; Trace Data Replay.
|
|
|
|
|
|
|
|
|
|
(defvar eat--trace-replay-buffer nil
|
|
|
|
|
"The buffer replaying the trace data in current buffer.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--trace-replay-marker nil
|
|
|
|
|
"The point from where to read the next sexp.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--trace-replay-current-sexp-overlay nil
|
|
|
|
|
"Overlay indicating the current sexp.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--trace-replay-source-buffer nil
|
|
|
|
|
"The source buffer containing the trace output.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--trace-replay-recording-start-time 0.0
|
|
|
|
|
"Time when recording was started.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--trace-replay-frame-count 0
|
|
|
|
|
"The number of the frames in the trace output.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--trace-replay-progress-frame 0
|
|
|
|
|
"The number of the frames before the current position.")
|
|
|
|
|
|
|
|
|
|
(defvar eat--trace-replay-progress nil
|
|
|
|
|
"The number of seconds of trace output was shown.")
|
|
|
|
|
|
|
|
|
|
(defun eat--trace-replay-eval (data)
|
|
|
|
|
"Evalulate DATA as trace output."
|
|
|
|
|
(let ((inhibit-read-only t))
|
|
|
|
|
(setq eat--trace-replay-progress
|
|
|
|
|
(- (car data) eat--trace-replay-recording-start-time))
|
2022-11-28 22:29:15 +06:00
|
|
|
|
(pcase-exhaustive data
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(`(,time create ,_ui ,width ,height ,variables)
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setq eat--trace-replay-recording-start-time time)
|
|
|
|
|
(setq eat--trace-replay-progress 0)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(dolist (var eat--trace-recorded-variables)
|
|
|
|
|
(set (make-local-variable var) (alist-get var variables)))
|
|
|
|
|
(setq eat--terminal (eat-term-make (current-buffer) (point)))
|
|
|
|
|
(setf (eat-term-set-cursor-function eat--terminal)
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
#'eat--set-cursor)
|
|
|
|
|
(setf (eat-term-ring-bell-function eat--terminal) #'eat--bell)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(eat-term-resize eat--terminal width height)
|
|
|
|
|
(eat-term-redisplay eat--terminal))
|
|
|
|
|
(`(,_time output ,string)
|
|
|
|
|
(eat-term-process-output eat--terminal string))
|
|
|
|
|
(`(,_time redisplay)
|
|
|
|
|
(eat-term-redisplay eat--terminal))
|
|
|
|
|
(`(,_time resize ,width ,height)
|
|
|
|
|
(eat-term-resize eat--terminal width height))
|
|
|
|
|
(`(,_time reset)
|
|
|
|
|
(eat-term-reset eat--terminal))
|
|
|
|
|
(`(,_time finish)
|
|
|
|
|
(eat-term-delete eat--terminal)))
|
2022-12-12 14:00:57 +06:00
|
|
|
|
(eat--synchronize-scroll (get-buffer-window-list))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
|
|
|
|
|
(defun eat--trace-replay-eval-next ()
|
|
|
|
|
"Evaluate next sexp in trace output."
|
|
|
|
|
(with-current-buffer eat--trace-replay-source-buffer
|
|
|
|
|
(goto-char eat--trace-replay-marker)
|
|
|
|
|
(ignore-error end-of-file
|
|
|
|
|
(let ((data (read (current-buffer))))
|
|
|
|
|
(set-marker eat--trace-replay-marker (point))
|
|
|
|
|
(backward-list)
|
|
|
|
|
(move-overlay eat--trace-replay-current-sexp-overlay
|
|
|
|
|
(point) (point))
|
2022-11-28 23:22:52 +06:00
|
|
|
|
(when-let* ((window (get-buffer-window)))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(set-window-point window (point)))
|
|
|
|
|
(with-current-buffer eat--trace-replay-buffer
|
|
|
|
|
(cl-incf eat--trace-replay-progress-frame)
|
|
|
|
|
(eat--trace-replay-eval data))))))
|
|
|
|
|
|
|
|
|
|
(defun eat-trace-replay ()
|
|
|
|
|
"Replay terminal according to trace output in current buffer."
|
|
|
|
|
(interactive)
|
|
|
|
|
(unless (buffer-live-p eat--trace-replay-buffer)
|
|
|
|
|
(setq-local eat--trace-replay-buffer
|
|
|
|
|
(generate-new-buffer
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(format "*eat-trace-replay*: %s" (buffer-name))))
|
|
|
|
|
(setq-local eat--trace-replay-marker (point-min-marker))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(let ((ov (make-overlay (point-min) (point-min))))
|
|
|
|
|
(overlay-put ov 'before-string
|
Use as less let-bindings as possible
* eat.el (eat--t-goto-bol, eat--t-goto-eol)
(eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
(eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
(eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
(eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
(eat--t-write, eat--t-horizontal-tab)
(eat--t-horizontal-backtab, eat--t-reverse-index)
(eat--t-erase-in-line, eat--t-erase-in-disp)
(eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
(eat--t-insert-line, eat--t-delete-line)
(eat--t-repeat-last-char, eat--t-change-scroll-region)
(eat--t-send-device-attrs): Minimize let-binding count.
* eat.el (eat--t-break-long-line, eat--t-write)
(eat-trace-replay): Use replace 'propertize' call with already
propertized string.
2022-11-28 17:41:51 +06:00
|
|
|
|
#(" " 0 1 (display (left-fringe right-triangle))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(setq-local eat--trace-replay-current-sexp-overlay ov))
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(let ((source (current-buffer))
|
|
|
|
|
(frame-count 0))
|
|
|
|
|
(ignore-error end-of-file
|
|
|
|
|
(while (read (current-buffer))
|
|
|
|
|
(cl-incf frame-count)))
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(with-current-buffer eat--trace-replay-buffer
|
|
|
|
|
(eat-trace-replay-mode)
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setq eat--trace-replay-source-buffer source)
|
|
|
|
|
(setq eat--trace-replay-frame-count frame-count))))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(display-buffer eat--trace-replay-buffer))
|
|
|
|
|
|
|
|
|
|
(defun eat-trace-replay-next-frame (&optional n)
|
|
|
|
|
"Show the Nth next frame.
|
|
|
|
|
|
|
|
|
|
N defaults to 1. Interactively, N is the prefix argument."
|
|
|
|
|
(interactive "p")
|
|
|
|
|
(dotimes (_ n)
|
|
|
|
|
(eat--trace-replay-eval-next)))
|
|
|
|
|
|
|
|
|
|
(defun eat-trace--cleanup ()
|
|
|
|
|
"Clean up the source buffer before the terminal being killed."
|
|
|
|
|
(when (buffer-live-p eat--trace-replay-source-buffer)
|
|
|
|
|
(with-current-buffer eat--trace-replay-source-buffer
|
Break combined 'setq'/'setf'/'setq-local's
When giving more than two arguments to 'setq', it becomes hard
to figure out what is assigned to what. As the number of
argument increases, the readablity of code decreases. This is
also true for 'setq-local'. For 'setf', the problem is even
greater, unlike 'setq', all arguments to 'setf' look the same.
* eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
(eat--t-restore-cur, eat--t-enable-alt-disp)
(eat--t-disable-alt-disp, eat--t-change-scroll-region)
(eat--t-set-sgr-params, eat--t-manipulate-selection)
(eat--t-resize, eat--blink-start-timers, eat-blink-mode)
(eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
(eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
(eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
(eat--eshell-local-mode, eat--eshell-exec-visual)
(eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
(eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
Break combined 'setq'/'setf'/'setq-local's.
2022-12-08 18:04:56 +06:00
|
|
|
|
(setq eat--trace-replay-buffer nil)
|
|
|
|
|
(setq eat--trace-replay-marker nil)
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(delete-overlay eat--trace-replay-current-sexp-overlay))))
|
|
|
|
|
|
|
|
|
|
(defvar eat-trace-replay-mode-map
|
|
|
|
|
(let ((map (make-sparse-keymap)))
|
|
|
|
|
(define-key map (kbd "n") #'eat-trace-replay-next-frame)
|
|
|
|
|
(define-key map (kbd "<down>") #'eat-trace-replay-next-frame)
|
|
|
|
|
(define-key map (kbd "q") #'quit-window)
|
|
|
|
|
map)
|
|
|
|
|
"Keymap for Eat-Trace-Replay mode.")
|
|
|
|
|
|
|
|
|
|
(define-derived-mode eat-trace-replay-mode special-mode
|
|
|
|
|
"Eat-Trace-Replay"
|
|
|
|
|
"Major mode for replaying terminal according to trace output."
|
2022-11-29 00:58:09 +06:00
|
|
|
|
(mapc #'make-local-variable '(eat--terminal
|
|
|
|
|
eat--trace-replay-source-buffer
|
|
|
|
|
eat--trace-replay-recording-start-time
|
|
|
|
|
eat--trace-replay-progress
|
|
|
|
|
eat--trace-replay-frame-count
|
|
|
|
|
eat--trace-replay-progress-frame))
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(setq-local
|
|
|
|
|
mode-line-process
|
|
|
|
|
'("[" (:eval (number-to-string eat--trace-replay-progress-frame))
|
|
|
|
|
"/" (:eval (number-to-string eat--trace-replay-frame-count))
|
|
|
|
|
"]"))
|
|
|
|
|
(add-hook 'kill-buffer-hook #'eat-trace--cleanup nil t))
|
|
|
|
|
|
2023-03-30 13:25:16 +06:00
|
|
|
|
|
|
|
|
|
;;;; Miscellaneous.
|
|
|
|
|
|
|
|
|
|
(defun eat-compile-terminfo ()
|
|
|
|
|
"Compile terminfo databases of Eat."
|
|
|
|
|
(interactive)
|
|
|
|
|
;; Check for required files and programs.
|
|
|
|
|
(let ((source-path (expand-file-name "eat.ti" eat--install-path))
|
|
|
|
|
(tic-path (executable-find "tic")))
|
|
|
|
|
(unless (file-exists-p source-path)
|
|
|
|
|
(error "Eat not installed properly: %s"
|
|
|
|
|
"Terminfo source file not found"))
|
|
|
|
|
(unless tic-path
|
|
|
|
|
(error "Terminfo compiler `tic' not found"))
|
|
|
|
|
(message "Compiling terminfo databases...")
|
|
|
|
|
;; Compile.
|
|
|
|
|
(let* ((command (format "env TERMINFO=\"%s\" %s -x %s"
|
|
|
|
|
eat-term-terminfo-directory tic-path
|
|
|
|
|
source-path))
|
|
|
|
|
(status
|
|
|
|
|
(with-temp-buffer
|
|
|
|
|
(make-directory eat-term-terminfo-directory 'parents)
|
|
|
|
|
(let ((proc (start-process-shell-command
|
|
|
|
|
"eat-terminfo-compile"
|
|
|
|
|
(current-buffer) command)))
|
|
|
|
|
(while (process-live-p proc)
|
|
|
|
|
(sleep-for 0.02))
|
|
|
|
|
(process-exit-status proc)))))
|
|
|
|
|
(if (= status 0)
|
|
|
|
|
(message "Compiling terminfo databases...done")
|
|
|
|
|
(message "Compiling terminfo databases...error")
|
|
|
|
|
(error "Command `%s' exited with non-zero exit code %i"
|
|
|
|
|
command status)))))
|
|
|
|
|
|
2023-01-19 15:45:44 +06:00
|
|
|
|
|
|
|
|
|
;;;; Footer.
|
|
|
|
|
|
|
|
|
|
(defun eat-reload ()
|
|
|
|
|
"Reload Eat."
|
|
|
|
|
(interactive)
|
|
|
|
|
(unless eat--being-loaded
|
|
|
|
|
;; Remove .elc suffix to load native compiled version if possible.
|
|
|
|
|
(load (string-remove-suffix ".elc" eat--load-file-path))))
|
|
|
|
|
|
|
|
|
|
(setq eat--being-loaded nil)
|
|
|
|
|
|
2022-09-02 20:03:33 +06:00
|
|
|
|
(provide 'eat)
|
|
|
|
|
;;; eat.el ends here
|