summaryrefslogtreecommitdiff
path: root/lisp/eshell/em-glob.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/eshell/em-glob.el')
-rw-r--r--lisp/eshell/em-glob.el77
1 files changed, 46 insertions, 31 deletions
diff --git a/lisp/eshell/em-glob.el b/lisp/eshell/em-glob.el
index 02f2fffe94f..7fc6958a00f 100644
--- a/lisp/eshell/em-glob.el
+++ b/lisp/eshell/em-glob.el
@@ -49,8 +49,9 @@
;;; Code:
+(require 'esh-arg)
+(require 'esh-module)
(require 'esh-util)
-(eval-when-compile (require 'eshell))
;;;###autoload
(progn
@@ -68,6 +69,15 @@ by zsh for filename generation."
:type 'hook
:group 'eshell-glob)
+(defcustom eshell-glob-splice-results nil
+ "If non-nil, the results of glob patterns will be spliced in-place.
+When splicing, the resulting command is as though the user typed
+each result individually. Otherwise, the glob results a single
+argument as a list."
+ :version "30.1"
+ :type 'boolean
+ :group 'eshell-glob)
+
(defcustom eshell-glob-include-dot-files nil
"If non-nil, glob patterns will match files beginning with a dot."
:type 'boolean
@@ -78,7 +88,7 @@ by zsh for filename generation."
:type 'boolean
:group 'eshell-glob)
-(defcustom eshell-glob-case-insensitive (eshell-under-windows-p)
+(defcustom eshell-glob-case-insensitive (not (not (eshell-under-windows-p)))
"If non-nil, glob pattern matching will ignore case."
:type 'boolean
:group 'eshell-glob)
@@ -138,23 +148,16 @@ This mimics the behavior of zsh if non-nil, but bash if nil."
(defun eshell-no-command-globbing (terms)
"Don't glob the command argument. Reflect this by modifying TERMS."
(ignore
- (when (and (listp (car terms))
- (eq (caar terms) 'eshell-extended-glob))
- (setcar terms (cadr (car terms))))))
+ (pcase (car terms)
+ ((or `(eshell-extended-glob ,term)
+ `(eshell-splice-args (eshell-extended-glob ,term)))
+ (setcar terms term)))))
(defun eshell-add-glob-modifier ()
"Add `eshell-extended-glob' to the argument modifier list."
- (when (memq 'expand-file-name eshell-current-modifiers)
- (setq eshell-current-modifiers
- (delq 'expand-file-name eshell-current-modifiers))
- ;; if this is a glob pattern than needs to be expanded, then it
- ;; will need to expand each member of the resulting glob list
- (add-to-list 'eshell-current-modifiers
- (lambda (list)
- (if (listp list)
- (mapcar 'expand-file-name list)
- (expand-file-name list)))))
- (add-to-list 'eshell-current-modifiers 'eshell-extended-glob))
+ (when eshell-glob-splice-results
+ (add-hook 'eshell-current-modifiers #'eshell-splice-args 99))
+ (add-hook 'eshell-current-modifiers #'eshell-extended-glob))
(defun eshell-parse-glob-chars ()
"Parse a globbing delimiter.
@@ -170,7 +173,7 @@ interpretation."
(end (eshell-find-delimiter
delim (if (eq delim ?\[) ?\] ?\)))))
(if (not end)
- (throw 'eshell-incomplete delim)
+ (throw 'eshell-incomplete (char-to-string delim))
(if (and (eshell-using-module 'eshell-pred)
(eshell-arg-delimiter (1+ end)))
(ignore (goto-char here))
@@ -187,6 +190,12 @@ interpretation."
'(("**/" . recurse)
("***/" . recurse-symlink)))
+(defsubst eshell-glob-chars-regexp ()
+ "Return the lazily-created value for `eshell-glob-chars-regexp'."
+ (or eshell-glob-chars-regexp
+ (setq-local eshell-glob-chars-regexp
+ (format "[%s]+" (apply 'string eshell-glob-chars-list)))))
+
(defun eshell-glob-regexp (pattern)
"Convert glob-pattern PATTERN to a regular expression.
The basic syntax is:
@@ -207,11 +216,8 @@ set to true, then these characters will match themselves in the
resulting regular expression."
(let ((matched-in-pattern 0) ; How much of PATTERN handled
regexp)
- (while (string-match
- (or eshell-glob-chars-regexp
- (setq-local eshell-glob-chars-regexp
- (format "[%s]+" (apply 'string eshell-glob-chars-list))))
- pattern matched-in-pattern)
+ (while (string-match (eshell-glob-chars-regexp)
+ pattern matched-in-pattern)
(let* ((op-begin (match-beginning 0))
(op-char (aref pattern op-begin)))
(setq regexp
@@ -236,6 +242,10 @@ resulting regular expression."
(regexp-quote (substring pattern matched-in-pattern))
"\\'")))
+(defun eshell-glob-p (pattern)
+ "Return non-nil if PATTERN has any special glob characters."
+ (string-match (eshell-glob-chars-regexp) pattern))
+
(defun eshell-glob-convert-1 (glob &optional last)
"Convert a GLOB matching a single element of a file name to regexps.
If LAST is non-nil, this glob is the last element of a file name.
@@ -288,14 +298,13 @@ The result is a list of three elements:
symlinks.
3. A boolean indicating whether to match directories only."
- (let ((globs (eshell-split-path glob))
- (isdir (eq (aref glob (1- (length glob))) ?/))
+ (let ((globs (eshell-split-filename glob))
+ (isdir (string-suffix-p "/" glob))
start-dir result last-saw-recursion)
(if (and (cdr globs)
(file-name-absolute-p (car globs)))
- (setq start-dir (car globs)
- globs (cdr globs))
- (setq start-dir "."))
+ (setq start-dir (pop globs))
+ (setq start-dir (file-name-as-directory ".")))
(while globs
(if-let ((recurse (cdr (assoc (car globs)
eshell-glob-recursive-alist))))
@@ -303,11 +312,15 @@ The result is a list of three elements:
(setcar result recurse)
(push recurse result)
(setq last-saw-recursion t))
- (push (eshell-glob-convert-1 (car globs) (null (cdr globs)))
- result)
+ (if (or result (eshell-glob-p (car globs)))
+ (push (eshell-glob-convert-1 (car globs) (null (cdr globs)))
+ result)
+ ;; We haven't seen a glob yet, so instead append to the start
+ ;; directory.
+ (setq start-dir (file-name-concat start-dir (car globs))))
(setq last-saw-recursion nil))
(setq globs (cdr globs)))
- (list (file-name-as-directory start-dir)
+ (list start-dir
(nreverse result)
isdir)))
@@ -335,7 +348,9 @@ regular expressions, and these cannot support the above constructs."
(or (and eshell-glob-matches (sort eshell-glob-matches #'string<))
(if eshell-error-if-no-glob
(error "No matches found: %s" glob)
- glob))))
+ (if eshell-glob-splice-results
+ (list glob)
+ glob)))))
;; FIXME does this really need to abuse eshell-glob-matches, message-shown?
(defun eshell-glob-entries (path globs only-dirs)