unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
blob 60f2c6e4039ad2fcc2aa695798a365e65203d4a4 4392 bytes (raw)
name: lisp/eshell/em-elecslash.el 	 # note: path name is non-authoritative(*)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
 
;;; em-elecslash.el --- electric forward slashes  -*- lexical-binding:t -*-

;; Copyright (C) 2022-2024 Free Software Foundation, Inc.

;; Author: Sean Whitton <spwhitton@spwhitton.name>

;; 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:

;; Electric forward slash in remote Eshells.

;;; Code:

(require 'tramp)
(require 'thingatpt)
(require 'esh-cmd)
(require 'esh-ext)
(require 'esh-mode)

;; This makes us an option when customizing `eshell-modules-list'.
;;;###esh-module-autoload
(progn
(defgroup eshell-elecslash nil
  "Electric forward slash in remote Eshells.

This module helps with supplying absolute file name arguments to
remote commands.  After enabling it, typing a forward slash as
the first character of a command line argument will automatically
insert the Tramp prefix, /method:host:.  The automatic insertion
applies only when `default-directory' is remote and the command
is a Lisp function.

The result is that in most cases of supplying absolute file name
arguments to commands you should see the Tramp prefix inserted
automatically only when that's what you'd reasonably expect.
This frees you from having to keep track of whether commands are
Lisp functions or external when typing command line arguments."
  :tag "Electric forward slash"
  :group 'eshell-module))

;;; Functions:

(defun eshell-elecslash-initialize () ;Called from `eshell-mode' via intern-soft!
  "Initialize remote Eshell electric forward slash support."
  (add-hook 'post-self-insert-hook
            #'eshell-electric-forward-slash nil t))

(defun eshell-electric-forward-slash ()
  "Implementation of electric forward slash in remote Eshells.

Initializing the `eshell-elecslash' module adds this function to
`post-self-insert-hook'.  Typing / or ~/ as the first character
of a command line argument automatically inserts the Tramp prefix
in the case that `default-directory' is remote and the command is
a Lisp function.  Typing a second forward slash undoes the
insertion."
  (when (eq ?/ (char-before))
    (delete-char -1)
    (let ((tilde-before (eq ?~ (char-before)))
          (command (save-excursion
                     (beginning-of-line)
                     (skip-syntax-forward " ")
                     (thing-at-point 'sexp)))
          (prefix (file-remote-p default-directory)))
      (if (and prefix
               ;; We can't formally parse the input.  But if there is
               ;; one of these operators behind us, then looking at
               ;; the first command would not be sensible.  So be
               ;; conservative: don't insert the Tramp prefix if there
               ;; are any of these operators behind us.
               (not (looking-back (regexp-opt '("&&" "|" ";"))
                                  eshell-last-output-end))
	       (or (= (point) eshell-last-output-end)
		   (and tilde-before
                        (= (1- (point)) eshell-last-output-end))
		   (and (or tilde-before
                            (eq ?\s (char-syntax (char-before))))
		        (or (eshell-find-alias-function command)
			    (and (fboundp (intern-soft command))
			         (or eshell-prefer-lisp-functions
				     (not (eshell-search-path command))))))))
	  (let ((map (make-sparse-keymap))
	        (start (if tilde-before (1- (point)) (point))))
	    (when tilde-before (delete-char -1))
	    (insert prefix)
	    (unless tilde-before (insert "/"))
	    ;; Typing a second slash undoes the insertion, for when
	    ;; you really do want to type a local absolute file name.
	    (define-key map "/" (lambda ()
				  (interactive)
				  (delete-region start (point))
				  (insert (if tilde-before "~/" "/"))))
	    (set-transient-map map))
        (insert "/")))))

(provide 'em-elecslash)
;;; esh-elecslash.el ends here

debug log:

solving 60f2c6e4039 ...
found 60f2c6e4039 in https://git.savannah.gnu.org/cgit/emacs.git

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).