mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-11 00:30:17 -08:00
dc4e6b1329; Update copyright years in more files64b3777631; Run set-copyright from admin.el8e1c56ae46; Add 2024 to copyright years # Conflicts: # doc/misc/modus-themes.org # doc/misc/texinfo.tex # etc/NEWS # etc/refcards/ru-refcard.tex # etc/themes/modus-operandi-theme.el # etc/themes/modus-themes.el # etc/themes/modus-vivendi-theme.el # lib/alloca.in.h # lib/binary-io.h # lib/c-ctype.h # lib/c-strcasecmp.c # lib/c-strncasecmp.c # lib/careadlinkat.c # lib/cloexec.c # lib/close-stream.c # lib/diffseq.h # lib/dup2.c # lib/filemode.h # lib/fpending.c # lib/fpending.h # lib/fsusage.c # lib/getgroups.c # lib/getloadavg.c # lib/gettext.h # lib/gettime.c # lib/gettimeofday.c # lib/group-member.c # lib/malloc.c # lib/md5-stream.c # lib/md5.c # lib/md5.h # lib/memmem.c # lib/memrchr.c # lib/nanosleep.c # lib/save-cwd.h # lib/sha1.c # lib/sig2str.c # lib/stdlib.in.h # lib/strtoimax.c # lib/strtol.c # lib/strtoll.c # lib/time_r.c # lib/xalloc-oversized.h # lisp/auth-source-pass.el # lisp/emacs-lisp/lisp-mnt.el # lisp/emacs-lisp/timer.el # lisp/info-look.el # lisp/jit-lock.el # lisp/loadhist.el # lisp/mail/rmail.el # lisp/net/ntlm.el # lisp/net/webjump.el # lisp/progmodes/asm-mode.el # lisp/progmodes/project.el # lisp/progmodes/sh-script.el # lisp/textmodes/flyspell.el # lisp/textmodes/reftex-toc.el # lisp/textmodes/reftex.el # lisp/textmodes/tex-mode.el # lisp/url/url-gw.el # m4/alloca.m4 # m4/clock_time.m4 # m4/d-type.m4 # m4/dirent_h.m4 # m4/dup2.m4 # m4/euidaccess.m4 # m4/fchmodat.m4 # m4/filemode.m4 # m4/fsusage.m4 # m4/getgroups.m4 # m4/getloadavg.m4 # m4/getrandom.m4 # m4/gettime.m4 # m4/gettimeofday.m4 # m4/gnulib-common.m4 # m4/group-member.m4 # m4/inttypes.m4 # m4/malloc.m4 # m4/manywarnings.m4 # m4/mempcpy.m4 # m4/memrchr.m4 # m4/mkostemp.m4 # m4/mktime.m4 # m4/nproc.m4 # m4/nstrftime.m4 # m4/pathmax.m4 # m4/pipe2.m4 # m4/pselect.m4 # m4/pthread_sigmask.m4 # m4/readlink.m4 # m4/realloc.m4 # m4/sig2str.m4 # m4/ssize_t.m4 # m4/stat-time.m4 # m4/stddef_h.m4 # m4/stdint.m4 # m4/stdio_h.m4 # m4/stdlib_h.m4 # m4/stpcpy.m4 # m4/strnlen.m4 # m4/strtoimax.m4 # m4/strtoll.m4 # m4/time_h.m4 # m4/timegm.m4 # m4/timer_time.m4 # m4/timespec.m4 # m4/unistd_h.m4 # m4/warnings.m4 # nt/configure.bat # nt/preprep.c # test/lisp/register-tests.el
258 lines
8 KiB
EmacsLisp
258 lines
8 KiB
EmacsLisp
;;; em-rebind.el --- rebind keys when point is at current input -*- lexical-binding:t -*-
|
|
|
|
;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
|
|
|
|
;; Author: John Wiegley <johnw@gnu.org>
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
;; GNU Emacs 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 of the License, or
|
|
;; (at your option) any later version.
|
|
|
|
;; GNU Emacs 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.
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
;;; Commentary:
|
|
|
|
;;; Code:
|
|
|
|
(require 'esh-mode)
|
|
|
|
;;;###autoload
|
|
(progn
|
|
(defgroup eshell-rebind nil
|
|
"This module allows for special keybindings that only take effect
|
|
while the point is in a region of input text. The default
|
|
keybindings mimic the bindings used in other shells when the user
|
|
is editing new input text.
|
|
|
|
For example, it binds C-u to kill the current input text and C-w
|
|
to `backward-kill-word'. If the history module is enabled, it
|
|
also binds C-p and C-n to move through the input history, etc.
|
|
|
|
If `eshell-confine-point-to-input' is non-nil, this module prevents
|
|
certain commands from causing the point to leave the input area, such
|
|
as `backward-word', `previous-line', etc."
|
|
:tag "Rebind keys at input"
|
|
:group 'eshell-module))
|
|
|
|
;;; User Variables:
|
|
|
|
(defcustom eshell-rebind-load-hook nil
|
|
"A list of functions to call when loading `eshell-rebind'."
|
|
:version "24.1" ; removed eshell-rebind-initialize
|
|
:type 'hook
|
|
:group 'eshell-rebind)
|
|
|
|
(defcustom eshell-rebind-keys-alist
|
|
'(([(control ?d)] . eshell-delchar-or-maybe-eof)
|
|
([backspace] . eshell-delete-backward-char)
|
|
([delete] . eshell-delete-backward-char)
|
|
([(control ?w)] . backward-kill-word)
|
|
([(control ?u)] . eshell-kill-input))
|
|
"Bind some keys differently if point is in input text."
|
|
:type '(repeat (cons (vector :tag "Keys to bind"
|
|
(repeat :inline t sexp))
|
|
(function :tag "Command")))
|
|
:group 'eshell-rebind)
|
|
|
|
(defcustom eshell-confine-point-to-input t
|
|
"If non-nil, do not allow the point to leave the current input.
|
|
This is more difficult to do nicely in Emacs than one might think.
|
|
Basically, the `point-left' attribute is added to the input text, and
|
|
a function is placed on that hook to take the point back to
|
|
`eshell-last-output-end' every time the user tries to move away. But
|
|
since there are many cases in which the point _ought_ to move away
|
|
\(for programmatic reasons), the variable
|
|
`eshell-cannot-leave-input-list' defines commands which are affected
|
|
from this rule. However, this list is by no means as complete as it
|
|
probably should be, so basically all one can hope for is that other
|
|
people will left the point alone in the Eshell buffer. Sigh."
|
|
:type 'boolean
|
|
:group 'eshell-rebind)
|
|
|
|
(defcustom eshell-error-if-move-away t
|
|
"If non-nil, consider it an error to try to move outside current input.
|
|
This is default behavior of shells like bash."
|
|
:type 'boolean
|
|
:group 'eshell-rebind)
|
|
|
|
(defcustom eshell-remap-previous-input t
|
|
"If non-nil, remap input keybindings on previous prompts as well."
|
|
:type 'boolean
|
|
:group 'eshell-rebind)
|
|
|
|
(defcustom eshell-cannot-leave-input-list
|
|
'(beginning-of-line-text
|
|
beginning-of-line
|
|
move-to-column
|
|
move-to-left-margin
|
|
move-to-tab-stop
|
|
forward-char
|
|
backward-char
|
|
delete-char
|
|
delete-backward-char
|
|
backward-delete-char
|
|
backward-delete-char-untabify
|
|
kill-paragraph
|
|
backward-kill-paragraph
|
|
kill-sentence
|
|
backward-kill-sentence
|
|
kill-sexp
|
|
backward-kill-sexp
|
|
kill-word
|
|
backward-kill-word
|
|
kill-region
|
|
forward-list
|
|
backward-list
|
|
forward-page
|
|
backward-page
|
|
forward-paragraph
|
|
backward-paragraph
|
|
backward-prefix-chars
|
|
forward-sentence
|
|
backward-sentence
|
|
forward-sexp
|
|
backward-sexp
|
|
forward-to-indentation
|
|
backward-to-indentation
|
|
backward-up-list
|
|
forward-word
|
|
backward-word
|
|
forward-line
|
|
previous-line
|
|
next-line
|
|
forward-visible-line
|
|
forward-comment
|
|
forward-thing)
|
|
"A list of commands that cannot leave the input area."
|
|
:type '(repeat function)
|
|
:group 'eshell-rebind)
|
|
|
|
(defvar-keymap eshell-rebind-mode-map
|
|
"C-c M-l" #'eshell-lock-local-map)
|
|
|
|
;; Internal Variables:
|
|
|
|
(defvar eshell-input-keymap)
|
|
(defvar eshell-previous-point)
|
|
(defvar eshell-lock-keymap)
|
|
|
|
;;; Functions:
|
|
|
|
(define-minor-mode eshell-rebind-mode
|
|
"Minor mode for the eshell-rebind module.
|
|
|
|
\\{eshell-rebind-mode-map}"
|
|
:keymap eshell-rebind-mode-map)
|
|
|
|
(defun eshell-rebind-initialize () ;Called from `eshell-mode' via intern-soft!
|
|
"Initialize the inputting code."
|
|
(unless eshell-non-interactive-p
|
|
(add-hook 'eshell-mode-hook 'eshell-setup-input-keymap nil t)
|
|
(make-local-variable 'eshell-previous-point)
|
|
(add-hook 'pre-command-hook 'eshell-save-previous-point nil t)
|
|
(make-local-variable 'overriding-local-map)
|
|
(add-hook 'post-command-hook 'eshell-rebind-input-map nil t)
|
|
(setq-local eshell-lock-keymap nil)
|
|
(eshell-rebind-mode)))
|
|
|
|
(defun eshell-lock-local-map (&optional arg)
|
|
"Lock or unlock the current local keymap.
|
|
With prefix ARG, set the local keymap to its normal value, and
|
|
lock it at that."
|
|
(interactive "P")
|
|
(if (or arg (not eshell-lock-keymap))
|
|
(progn
|
|
(use-local-map eshell-mode-map)
|
|
(setq eshell-lock-keymap t)
|
|
(message "Local keymap locked in normal mode"))
|
|
(use-local-map eshell-input-keymap)
|
|
(setq eshell-lock-keymap nil)
|
|
(message "Local keymap unlocked: obey context")))
|
|
|
|
(defun eshell-save-previous-point ()
|
|
"Save the location of point before the next command is run."
|
|
(setq eshell-previous-point (point)))
|
|
|
|
(defsubst eshell-point-within-input-p (pos)
|
|
"Test whether POS is within an input range."
|
|
(let (begin)
|
|
(or (and (>= pos eshell-last-output-end)
|
|
eshell-last-output-end)
|
|
(and eshell-remap-previous-input
|
|
(setq begin
|
|
(save-excursion
|
|
(beginning-of-line)
|
|
(and (not (bolp)) (point))))
|
|
(>= pos begin)
|
|
(<= pos (line-end-position))
|
|
begin))))
|
|
|
|
(defun eshell-rebind-input-map ()
|
|
"Rebind the input keymap based on the location of the cursor."
|
|
(ignore-errors
|
|
(unless eshell-lock-keymap
|
|
(if (eshell-point-within-input-p (point))
|
|
(use-local-map eshell-input-keymap)
|
|
(let (begin)
|
|
(if (and eshell-confine-point-to-input
|
|
(setq begin
|
|
(eshell-point-within-input-p eshell-previous-point))
|
|
(memq this-command eshell-cannot-leave-input-list))
|
|
(progn
|
|
(use-local-map eshell-input-keymap)
|
|
(goto-char begin)
|
|
(if (and eshell-error-if-move-away
|
|
(not (eq this-command 'kill-region)))
|
|
(beep)))
|
|
(use-local-map eshell-mode-map)))))))
|
|
|
|
(defun eshell-setup-input-keymap ()
|
|
"Setup the input keymap to be used during input editing."
|
|
(setq-local eshell-input-keymap (make-sparse-keymap))
|
|
(set-keymap-parent eshell-input-keymap eshell-mode-map)
|
|
(let ((bindings eshell-rebind-keys-alist))
|
|
(while bindings
|
|
(define-key eshell-input-keymap (caar bindings)
|
|
(cdar bindings))
|
|
(setq bindings (cdr bindings)))))
|
|
|
|
(defun eshell-delete-backward-char (n)
|
|
"Delete the last character, unless it's part of the output."
|
|
(interactive "P")
|
|
(let ((count (prefix-numeric-value n)))
|
|
(if (eshell-point-within-input-p (- (point) count))
|
|
(delete-char (- count) n)
|
|
(beep))))
|
|
|
|
(defun eshell-delchar-or-maybe-eof (arg)
|
|
"Delete ARG characters forward or send an EOF to subprocess.
|
|
Sends an EOF only if point is at the end of the buffer and there is no
|
|
input."
|
|
(interactive "p")
|
|
(let ((proc (eshell-head-process)))
|
|
(if (eobp)
|
|
(cond
|
|
((/= (point) eshell-last-output-end)
|
|
(beep))
|
|
(proc
|
|
(process-send-eof))
|
|
(t
|
|
(eshell-life-is-too-much)))
|
|
(eshell-delete-backward-char (- arg)))))
|
|
|
|
(provide 'em-rebind)
|
|
|
|
;; Local Variables:
|
|
;; generated-autoload-file: "esh-groups.el"
|
|
;; End:
|
|
|
|
;;; em-rebind.el ends here
|