aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2023-12-09 23:45:56 -0500
committerStefan Monnier2023-12-09 23:45:56 -0500
commit29957969e5199bdab5612af68e33b3989e4bbbd2 (patch)
tree6f23a222835492c8332bbde55ed1ba3724b30c33
parentf7cf85c3879c6857e8478bef41cce25a94759fb8 (diff)
downloademacs-29957969e5199bdab5612af68e33b3989e4bbbd2.tar.gz
emacs-29957969e5199bdab5612af68e33b3989e4bbbd2.zip
(insert-directory): Remove `ls-lisp` advice
Rather than have `ls-lisp` advise `insert-directory`, make `insert-directory` call `ls-lisp.el` code directly when needed. * lisp/files.el (files--use-insert-directory-program-p): New function. (insert-directory): Use it to delegate to `ls-lisp--insert-directory` when applicable. * lisp/ls-lisp.el (ls-lisp--insert-directory): Remove `orig-fun` arg. Don't test `ls-lisp-use-insert-directory-program` or check for a magic file name handler; it is now the caller's responsibility. (insert-directory): Don't add advice any more. * lisp/dired.el (ls-lisp-use-insert-directory-program): Don't declare it. (dired-insert-directory): Use `files--use-insert-directory-program-p` instead. (dired-use-ls-dired): Adjust docstring to refer to `insert-directory-program` rather than "ls".
-rw-r--r--lisp/dired.el21
-rw-r--r--lisp/files.el381
-rw-r--r--lisp/ls-lisp.el133
3 files changed, 263 insertions, 272 deletions
diff --git a/lisp/dired.el b/lisp/dired.el
index 9162dfbdf4b..c11b107213b 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -119,12 +119,11 @@ checks this alist to enable globstar in the shell subprocess.")
119(defcustom dired-use-ls-dired 'unspecified 119(defcustom dired-use-ls-dired 'unspecified
120 "Non-nil means Dired should pass the \"--dired\" option to \"ls\". 120 "Non-nil means Dired should pass the \"--dired\" option to \"ls\".
121If nil, don't pass \"--dired\" to \"ls\". 121If nil, don't pass \"--dired\" to \"ls\".
122The special value of `unspecified' means to check whether \"ls\" 122The special value of `unspecified' means to check whether
123supports the \"--dired\" option, and save the result in this 123`insert-directory-program' supports the \"--dired\" option, and save
124variable. This is performed the first time `dired-insert-directory' 124the result in this variable.
125is invoked. (If `ls-lisp' is used by default, the test is performed 125This is performed the first time `dired-insert-directory'
126only if `ls-lisp-use-insert-directory-program' is non-nil, i.e., if 126invokes `insert-directory-program'.
127Dired actually uses \"ls\".)
128 127
129Note that if you set this option to nil, either through choice or 128Note that if you set this option to nil, either through choice or
130because your \"ls\" program does not support \"--dired\", Dired 129because your \"ls\" program does not support \"--dired\", Dired
@@ -1643,9 +1642,6 @@ BEG..END is the line where the file info is located."
1643 (skip-chars-forward "^ ") (skip-chars-forward " ")) 1642 (skip-chars-forward "^ ") (skip-chars-forward " "))
1644 (set-marker file nil))))) 1643 (set-marker file nil)))))
1645 1644
1646
1647(defvar ls-lisp-use-insert-directory-program)
1648
1649(defun dired-check-switches (switches short &optional long) 1645(defun dired-check-switches (switches short &optional long)
1650 "Return non-nil if the string SWITCHES matches LONG or SHORT format." 1646 "Return non-nil if the string SWITCHES matches LONG or SHORT format."
1651 (let (case-fold-search) 1647 (let (case-fold-search)
@@ -1676,11 +1672,8 @@ If HDR is non-nil, insert a header line with the directory name."
1676 (remotep (file-remote-p dir)) 1672 (remotep (file-remote-p dir))
1677 end) 1673 end)
1678 (if (and 1674 (if (and
1679 ;; Don't try to invoke `ls' if we are on DOS/Windows where 1675 ;; Don't try to invoke `ls' if ls-lisp emulation should be used.
1680 ;; ls-lisp emulation is used, except if they want to use `ls' 1676 (files--use-insert-directory-program-p)
1681 ;; as indicated by `ls-lisp-use-insert-directory-program'.
1682 (not (and (featurep 'ls-lisp)
1683 (null ls-lisp-use-insert-directory-program)))
1684 ;; FIXME: Big ugly hack for Eshell's eshell-ls-use-in-dired. 1677 ;; FIXME: Big ugly hack for Eshell's eshell-ls-use-in-dired.
1685 (not (bound-and-true-p eshell-ls-use-in-dired)) 1678 (not (bound-and-true-p eshell-ls-use-in-dired))
1686 (or remotep 1679 (or remotep
diff --git a/lisp/files.el b/lisp/files.el
index 3c1d0c30e67..5e1987ec2ff 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -7780,6 +7780,16 @@ installing GNU coreutils using something like ports or Homebrew."
7780 :initialize #'custom-initialize-delay 7780 :initialize #'custom-initialize-delay
7781 :version "30.1") 7781 :version "30.1")
7782 7782
7783(defun files--use-insert-directory-program-p ()
7784 "Return non-nil if we should use `insert-directory-program'.
7785Return nil if we should prefer `ls-lisp' instead."
7786 ;; FIXME: Should we also check `file-accessible-directory-p' so we
7787 ;; automatically redirect to ls-lisp when operating on magic file names?
7788 (and (if (boundp 'ls-lisp-use-insert-directory-program)
7789 ls-lisp-use-insert-directory-program
7790 t)
7791 insert-directory-program))
7792
7783(defcustom directory-free-space-program (purecopy "df") 7793(defcustom directory-free-space-program (purecopy "df")
7784 "Program to get the amount of free space on a file system. 7794 "Program to get the amount of free space on a file system.
7785We assume the output has the format of `df'. 7795We assume the output has the format of `df'.
@@ -7972,9 +7982,11 @@ Optional third arg WILDCARD means treat FILE as shell wildcard.
7972Optional fourth arg FULL-DIRECTORY-P means file is a directory and 7982Optional fourth arg FULL-DIRECTORY-P means file is a directory and
7973switches do not contain `d', so that a full listing is expected. 7983switches do not contain `d', so that a full listing is expected.
7974 7984
7975This works by running a directory listing program 7985Depending on the value of `ls-lisp-use-insert-directory-program'
7976whose name is in the variable `insert-directory-program'. 7986this works either using a Lisp emulation of the \"ls\" program
7977If WILDCARD, it also runs the shell specified by `shell-file-name'. 7987or by running a directory listing program
7988whose name is in the variable `insert-directory-program'
7989\(and if WILDCARD, it also runs the shell specified by `shell-file-name').
7978 7990
7979When SWITCHES contains the long `--dired' option, this function 7991When SWITCHES contains the long `--dired' option, this function
7980treats it specially, for the sake of dired. However, the 7992treats it specially, for the sake of dired. However, the
@@ -7983,184 +7995,191 @@ normally equivalent short `-D' option is just passed on to
7983 ;; We need the directory in order to find the right handler. 7995 ;; We need the directory in order to find the right handler.
7984 (let ((handler (find-file-name-handler (expand-file-name file) 7996 (let ((handler (find-file-name-handler (expand-file-name file)
7985 'insert-directory))) 7997 'insert-directory)))
7986 (if handler 7998 (cond
7987 (funcall handler 'insert-directory file switches 7999 (handler
7988 wildcard full-directory-p) 8000 (funcall handler 'insert-directory file switches
7989 (let (result (beg (point))) 8001 wildcard full-directory-p))
7990 8002 ((not (files--use-insert-directory-program-p))
7991 ;; Read the actual directory using `insert-directory-program'. 8003 (require 'ls-lisp)
7992 ;; RESULT gets the status code. 8004 (declare-function ls-lisp--insert-directory "ls-lisp")
7993 (let* (;; We at first read by no-conversion, then after 8005 (ls-lisp--insert-directory file switches wildcard full-directory-p))
7994 ;; putting text property `dired-filename, decode one 8006 (t
7995 ;; bunch by one to preserve that property. 8007 (let (result (beg (point)))
7996 (coding-system-for-read 'no-conversion) 8008
7997 ;; This is to control encoding the arguments in call-process. 8009 ;; Read the actual directory using `insert-directory-program'.
7998 (coding-system-for-write 8010 ;; RESULT gets the status code.
7999 (and enable-multibyte-characters 8011 (let* (;; We at first read by no-conversion, then after
8000 (or file-name-coding-system 8012 ;; putting text property `dired-filename, decode one
8001 default-file-name-coding-system)))) 8013 ;; bunch by one to preserve that property.
8002 (setq result 8014 (coding-system-for-read 'no-conversion)
8003 (if wildcard 8015 ;; This is to control encoding the arguments in call-process.
8004 ;; If the wildcard is just in the file part, then run ls in 8016 (coding-system-for-write
8005 ;; the directory part of the file pattern using the last 8017 (and enable-multibyte-characters
8006 ;; component as argument. Otherwise, run ls in the longest 8018 (or file-name-coding-system
8007 ;; subdirectory of the directory part free of wildcards; use 8019 default-file-name-coding-system))))
8008 ;; the remaining of the file pattern as argument. 8020 (setq result
8009 (let* ((dir-wildcard (insert-directory-wildcard-in-dir-p file)) 8021 (if wildcard
8010 (default-directory 8022 ;; If the wildcard is just in the file part, then run ls in
8011 (cond (dir-wildcard (car dir-wildcard)) 8023 ;; the directory part of the file pattern using the last
8012 (t 8024 ;; component as argument. Otherwise, run ls in the longest
8013 (if (file-name-absolute-p file) 8025 ;; subdirectory of the directory part free of wildcards; use
8014 (file-name-directory file) 8026 ;; the remaining of the file pattern as argument.
8015 (file-name-directory (expand-file-name file)))))) 8027 (let* ((dir-wildcard (insert-directory-wildcard-in-dir-p file))
8016 (pattern (if dir-wildcard (cdr dir-wildcard) (file-name-nondirectory file)))) 8028 (default-directory
8017 ;; NB since switches is passed to the shell, be 8029 (cond (dir-wildcard (car dir-wildcard))
8018 ;; careful of malicious values, eg "-l;reboot". 8030 (t
8019 ;; See eg dired-safe-switches-p. 8031 (if (file-name-absolute-p file)
8020 (call-process 8032 (file-name-directory file)
8021 shell-file-name nil t nil 8033 (file-name-directory (expand-file-name file))))))
8022 shell-command-switch 8034 (pattern (if dir-wildcard (cdr dir-wildcard) (file-name-nondirectory file))))
8023 (concat (if (memq system-type '(ms-dos windows-nt)) 8035 ;; NB since switches is passed to the shell, be
8024 "" 8036 ;; careful of malicious values, eg "-l;reboot".
8025 "\\") ; Disregard Unix shell aliases! 8037 ;; See eg dired-safe-switches-p.
8026 insert-directory-program 8038 (call-process
8027 " -d " 8039 shell-file-name nil t nil
8028 (if (stringp switches) 8040 shell-command-switch
8029 switches 8041 (concat (if (memq system-type '(ms-dos windows-nt))
8030 (mapconcat 'identity switches " ")) 8042 ""
8031 " -- " 8043 "\\") ; Disregard Unix shell aliases!
8032 ;; Quote some characters that have 8044 insert-directory-program
8033 ;; special meanings in shells; but 8045 " -d "
8034 ;; don't quote the wildcards--we want 8046 (if (stringp switches)
8035 ;; them to be special. We also 8047 switches
8036 ;; currently don't quote the quoting 8048 (mapconcat #'identity switches " "))
8037 ;; characters in case people want to 8049 " -- "
8038 ;; use them explicitly to quote 8050 ;; Quote some characters that have
8039 ;; wildcard characters. 8051 ;; special meanings in shells; but
8040 (shell-quote-wildcard-pattern pattern)))) 8052 ;; don't quote the wildcards--we want
8041 ;; SunOS 4.1.3, SVr4 and others need the "." to list the 8053 ;; them to be special. We also
8042 ;; directory if FILE is a symbolic link. 8054 ;; currently don't quote the quoting
8043 (unless full-directory-p 8055 ;; characters in case people want to
8044 (setq switches 8056 ;; use them explicitly to quote
8045 (cond 8057 ;; wildcard characters.
8046 ((stringp switches) (concat switches " -d")) 8058 (shell-quote-wildcard-pattern pattern))))
8047 ((member "-d" switches) switches) 8059 ;; SunOS 4.1.3, SVr4 and others need the "." to list the
8048 (t (append switches '("-d")))))) 8060 ;; directory if FILE is a symbolic link.
8049 (if (string-match "\\`~" file) 8061 (unless full-directory-p
8050 (setq file (expand-file-name file))) 8062 (setq switches
8051 (apply 'call-process 8063 (cond
8052 insert-directory-program nil t nil 8064 ((stringp switches) (concat switches " -d"))
8053 (append 8065 ((member "-d" switches) switches)
8054 (if (listp switches) switches 8066 (t (append switches '("-d"))))))
8055 (unless (equal switches "") 8067 (if (string-match "\\`~" file)
8056 ;; Split the switches at any spaces so we can 8068 (setq file (expand-file-name file)))
8057 ;; pass separate options as separate args. 8069 (apply #'call-process
8058 (split-string-and-unquote switches))) 8070 insert-directory-program nil t nil
8059 ;; Avoid lossage if FILE starts with `-'. 8071 (append
8060 '("--") 8072 (if (listp switches) switches
8061 (list file)))))) 8073 (unless (equal switches "")
8062 8074 ;; Split the switches at any spaces so we can
8063 ;; If we got "//DIRED//" in the output, it means we got a real 8075 ;; pass separate options as separate args.
8064 ;; directory listing, even if `ls' returned nonzero. 8076 (split-string-and-unquote switches)))
8065 ;; So ignore any errors. 8077 ;; Avoid lossage if FILE starts with `-'.
8066 (when (if (stringp switches) 8078 '("--")
8067 (string-match "--dired\\>" switches) 8079 (list file))))))
8068 (member "--dired" switches)) 8080
8069 (save-excursion 8081 ;; If we got "//DIRED//" in the output, it means we got a real
8070 (forward-line -2) 8082 ;; directory listing, even if `ls' returned nonzero.
8071 (when (looking-at "//SUBDIRED//") 8083 ;; So ignore any errors.
8072 (forward-line -1)) 8084 (when (if (stringp switches)
8073 (if (looking-at "//DIRED//") 8085 (string-match "--dired\\>" switches)
8074 (setq result 0)))) 8086 (member "--dired" switches))
8075 8087 (save-excursion
8076 (when (and (not (eq 0 result)) 8088 (forward-line -2)
8077 (eq insert-directory-ls-version 'unknown)) 8089 (when (looking-at "//SUBDIRED//")
8078 ;; The first time ls returns an error, 8090 (forward-line -1))
8079 ;; find the version numbers of ls, 8091 (if (looking-at "//DIRED//")
8080 ;; and set insert-directory-ls-version 8092 (setq result 0))))
8081 ;; to > if it is more than 5.2.1, < if it is less, nil if it 8093
8082 ;; is equal or if the info cannot be obtained. 8094 (when (and (not (eq 0 result))
8083 ;; (That can mean it isn't GNU ls.) 8095 (eq insert-directory-ls-version 'unknown))
8084 (let ((version-out 8096 ;; The first time ls returns an error,
8085 (with-temp-buffer 8097 ;; find the version numbers of ls,
8086 (call-process "ls" nil t nil "--version") 8098 ;; and set insert-directory-ls-version
8087 (buffer-string)))) 8099 ;; to > if it is more than 5.2.1, < if it is less, nil if it
8088 (if (string-match "ls (.*utils) \\([0-9.]*\\)$" version-out) 8100 ;; is equal or if the info cannot be obtained.
8089 (let* ((version (match-string 1 version-out)) 8101 ;; (That can mean it isn't GNU ls.)
8090 (split (split-string version "[.]")) 8102 (let ((version-out
8091 (numbers (mapcar 'string-to-number split)) 8103 (with-temp-buffer
8092 (min '(5 2 1)) 8104 (call-process "ls" nil t nil "--version")
8093 comparison) 8105 (buffer-string))))
8094 (while (and (not comparison) (or numbers min)) 8106 (setq insert-directory-ls-version
8095 (cond ((null min) 8107 (if (string-match "ls (.*utils) \\([0-9.]*\\)$" version-out)
8096 (setq comparison '>)) 8108 (let* ((version (match-string 1 version-out))
8097 ((null numbers) 8109 (split (split-string version "[.]"))
8098 (setq comparison '<)) 8110 (numbers (mapcar #'string-to-number split))
8099 ((> (car numbers) (car min)) 8111 (min '(5 2 1))
8100 (setq comparison '>)) 8112 comparison)
8101 ((< (car numbers) (car min)) 8113 (while (and (not comparison) (or numbers min))
8102 (setq comparison '<)) 8114 (cond ((null min)
8103 (t 8115 (setq comparison #'>))
8104 (setq numbers (cdr numbers) 8116 ((null numbers)
8105 min (cdr min))))) 8117 (setq comparison #'<))
8106 (setq insert-directory-ls-version (or comparison '=))) 8118 ((> (car numbers) (car min))
8107 (setq insert-directory-ls-version nil)))) 8119 (setq comparison #'>))
8108 8120 ((< (car numbers) (car min))
8109 ;; For GNU ls versions 5.2.2 and up, ignore minor errors. 8121 (setq comparison #'<))
8110 (when (and (eq 1 result) (eq insert-directory-ls-version '>)) 8122 (t
8111 (setq result 0)) 8123 (setq numbers (cdr numbers)
8112 8124 min (cdr min)))))
8113 ;; If `insert-directory-program' failed, signal an error. 8125 (or comparison #'=))
8114 (unless (eq 0 result) 8126 nil))))
8115 ;; Delete the error message it may have output. 8127
8116 (delete-region beg (point)) 8128 ;; For GNU ls versions 5.2.2 and up, ignore minor errors.
8117 ;; On non-Posix systems, we cannot open a directory, so 8129 (when (and (eq 1 result) (eq insert-directory-ls-version #'>))
8118 ;; don't even try, because that will always result in 8130 (setq result 0))
8119 ;; the ubiquitous "Access denied". Instead, show the 8131
8120 ;; command line so the user can try to guess what went wrong. 8132 ;; If `insert-directory-program' failed, signal an error.
8121 (if (and (file-directory-p file) 8133 (unless (eq 0 result)
8122 (memq system-type '(ms-dos windows-nt))) 8134 ;; Delete the error message it may have output.
8123 (error 8135 (delete-region beg (point))
8124 "Reading directory: \"%s %s -- %s\" exited with status %s" 8136 ;; On non-Posix systems, we cannot open a directory, so
8125 insert-directory-program 8137 ;; don't even try, because that will always result in
8126 (if (listp switches) (concat switches) switches) 8138 ;; the ubiquitous "Access denied". Instead, show the
8127 file result) 8139 ;; command line so the user can try to guess what went wrong.
8128 ;; Unix. Access the file to get a suitable error. 8140 (if (and (file-directory-p file)
8129 (access-file file "Reading directory") 8141 (memq system-type '(ms-dos windows-nt)))
8130 (error "Listing directory failed but `access-file' worked"))) 8142 (error
8131 (insert-directory-clean beg switches) 8143 "Reading directory: \"%s %s -- %s\" exited with status %s"
8132 ;; Now decode what read if necessary. 8144 insert-directory-program
8133 (let ((coding (or coding-system-for-read 8145 (if (listp switches) (concat switches) switches)
8134 file-name-coding-system 8146 file result)
8135 default-file-name-coding-system 8147 ;; Unix. Access the file to get a suitable error.
8136 'undecided)) 8148 (access-file file "Reading directory")
8137 coding-no-eol 8149 (error "Listing directory failed but `access-file' worked")))
8138 val pos) 8150 (insert-directory-clean beg switches)
8139 (when (and enable-multibyte-characters 8151 ;; Now decode what read if necessary.
8140 (not (memq (coding-system-base coding) 8152 (let ((coding (or coding-system-for-read
8141 '(raw-text no-conversion)))) 8153 file-name-coding-system
8142 ;; If no coding system is specified or detection is 8154 default-file-name-coding-system
8143 ;; requested, detect the coding. 8155 'undecided))
8144 (if (eq (coding-system-base coding) 'undecided) 8156 coding-no-eol
8145 (setq coding (detect-coding-region beg (point) t))) 8157 val pos)
8146 (if (not (eq (coding-system-base coding) 'undecided)) 8158 (when (and enable-multibyte-characters
8147 (save-restriction 8159 (not (memq (coding-system-base coding)
8148 (setq coding-no-eol 8160 '(raw-text no-conversion))))
8149 (coding-system-change-eol-conversion coding 'unix)) 8161 ;; If no coding system is specified or detection is
8150 (narrow-to-region beg (point)) 8162 ;; requested, detect the coding.
8151 (goto-char (point-min)) 8163 (if (eq (coding-system-base coding) 'undecided)
8152 (while (not (eobp)) 8164 (setq coding (detect-coding-region beg (point) t)))
8153 (setq pos (point) 8165 (if (not (eq (coding-system-base coding) 'undecided))
8154 val (get-text-property (point) 'dired-filename)) 8166 (save-restriction
8155 (goto-char (next-single-property-change 8167 (setq coding-no-eol
8156 (point) 'dired-filename nil (point-max))) 8168 (coding-system-change-eol-conversion coding 'unix))
8157 ;; Force no eol conversion on a file name, so 8169 (narrow-to-region beg (point))
8158 ;; that CR is preserved. 8170 (goto-char (point-min))
8159 (decode-coding-region pos (point) 8171 (while (not (eobp))
8160 (if val coding-no-eol coding)) 8172 (setq pos (point)
8161 (if val 8173 val (get-text-property (point) 'dired-filename))
8162 (put-text-property pos (point) 8174 (goto-char (next-single-property-change
8163 'dired-filename t))))))))))) 8175 (point) 'dired-filename nil (point-max)))
8176 ;; Force no eol conversion on a file name, so
8177 ;; that CR is preserved.
8178 (decode-coding-region pos (point)
8179 (if val coding-no-eol coding))
8180 (if val
8181 (put-text-property pos (point)
8182 'dired-filename t))))))))))))
8164 8183
8165(defun insert-directory-adj-pos (pos error-lines) 8184(defun insert-directory-adj-pos (pos error-lines)
8166 "Convert `ls --dired' file name position value POS to a buffer position. 8185 "Convert `ls --dired' file name position value POS to a buffer position.
diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el
index 1066f38c050..141d1f32c09 100644
--- a/lisp/ls-lisp.el
+++ b/lisp/ls-lisp.el
@@ -249,89 +249,69 @@ to fail to line up, e.g. if month names are not all of the same length."
249 249
250;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 250;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
251 251
252(defun ls-lisp--insert-directory (orig-fun file switches &optional wildcard full-directory-p) 252(defun ls-lisp--insert-directory (file switches wildcard full-directory-p)
253 "Insert directory listing for FILE, formatted according to SWITCHES. 253 "Insert directory listing for FILE, formatted according to SWITCHES.
254Leaves point after the inserted text. 254This implementation of `insert-directory' works using Lisp functions rather
255SWITCHES may be a string of options, or a list of strings. 255than `insert-directory-program'.
256Optional third arg WILDCARD means treat FILE as shell wildcard. 256
257Optional fourth arg FULL-DIRECTORY-P means file is a directory and 257This Lisp emulation does not run any external programs or shells.
258switches do not contain `d', so that a full listing is expected. 258 It supports ordinary shell wildcards if `ls-lisp-support-shell-wildcards'
259
260This version of the function comes from `ls-lisp.el'.
261If the value of `ls-lisp-use-insert-directory-program' is non-nil then
262this advice just delegates the work to ORIG-FUN (the normal `insert-directory'
263function from `files.el').
264But if the value of `ls-lisp-use-insert-directory-program' is nil
265then it runs a Lisp emulation.
266
267The Lisp emulation does not run any external programs or shells. It
268supports ordinary shell wildcards if `ls-lisp-support-shell-wildcards'
269is non-nil; otherwise, it interprets wildcards as regular expressions 259is non-nil; otherwise, it interprets wildcards as regular expressions
270to match file names. It does not support all `ls' switches -- those 260to match file names. It does not support all `ls' switches -- those
271that work are: A a B C c F G g h i n R r S s t U u v X. The l switch 261that work are: A a B C c F G g h i n R r S s t U u v X. The l switch
272is assumed to be always present and cannot be turned off. 262is assumed to be always present and cannot be turned off.
273Long variants of the above switches, as documented for GNU `ls', 263Long variants of the above switches, as documented for GNU `ls',
274are also supported; unsupported long options are silently ignored." 264are also supported; unsupported long options are silently ignored."
275 (if ls-lisp-use-insert-directory-program 265 (setq switches (or switches ""))
276 (funcall orig-fun 266 (let ((orig-file file)
277 file switches wildcard full-directory-p) 267 wildcard-regexp
278 ;; We need the directory in order to find the right handler. 268 (ls-lisp-dirs-first
279 (setq switches (or switches "")) 269 (or ls-lisp-dirs-first
280 (let ((handler (find-file-name-handler (expand-file-name file) 270 (string-match "--group-directories-first" switches))))
281 'insert-directory)) 271 (when (string-match "--group-directories-first" switches)
282 (orig-file file) 272 ;; if ls-lisp-dirs-first is nil, dirs are grouped but come out in
283 wildcard-regexp 273 ;; reverse order:
284 (ls-lisp-dirs-first 274 (setq ls-lisp-dirs-first t)
285 (or ls-lisp-dirs-first 275 (setq switches (replace-match "" nil nil switches)))
286 (string-match "--group-directories-first" switches)))) 276 ;; Remove unrecognized long options, and convert the
287 (if handler 277 ;; recognized ones to their short variants.
288 (funcall handler 'insert-directory file switches 278 (setq switches (ls-lisp--sanitize-switches switches))
289 wildcard full-directory-p) 279 ;; Convert SWITCHES to a list of characters.
290 (when (string-match "--group-directories-first" switches) 280 (setq switches (delete ?\ (delete ?- (append switches nil))))
291 ;; if ls-lisp-dirs-first is nil, dirs are grouped but come out in 281 ;; Sometimes we get ".../foo*/" as FILE. While the shell and
292 ;; reverse order: 282 ;; `ls' don't mind, we certainly do, because it makes us think
293 (setq ls-lisp-dirs-first t) 283 ;; there is no wildcard, only a directory name.
294 (setq switches (replace-match "" nil nil switches))) 284 (if (and ls-lisp-support-shell-wildcards
295 ;; Remove unrecognized long options, and convert the 285 (string-match "[[?*]" file)
296 ;; recognized ones to their short variants. 286 ;; Prefer an existing file to wildcards, like
297 (setq switches (ls-lisp--sanitize-switches switches)) 287 ;; dired-noselect does.
298 ;; Convert SWITCHES to a list of characters. 288 (not (file-exists-p file)))
299 (setq switches (delete ?\ (delete ?- (append switches nil)))) 289 (progn
300 ;; Sometimes we get ".../foo*/" as FILE. While the shell and 290 (or (not (eq (aref file (1- (length file))) ?/))
301 ;; `ls' don't mind, we certainly do, because it makes us think 291 (setq file (substring file 0 (1- (length file)))))
302 ;; there is no wildcard, only a directory name. 292 (setq wildcard t)))
303 (if (and ls-lisp-support-shell-wildcards 293 (if wildcard
304 (string-match "[[?*]" file) 294 (setq wildcard-regexp
305 ;; Prefer an existing file to wildcards, like 295 (if ls-lisp-support-shell-wildcards
306 ;; dired-noselect does. 296 (wildcard-to-regexp (file-name-nondirectory file))
307 (not (file-exists-p file))) 297 (file-name-nondirectory file))
308 (progn 298 file (file-name-directory file))
309 (or (not (eq (aref file (1- (length file))) ?/)) 299 (if (memq ?B switches) (setq wildcard-regexp "[^~]\\'")))
310 (setq file (substring file 0 (1- (length file))))) 300 (condition-case err
311 (setq wildcard t))) 301 (ls-lisp-insert-directory
312 (if wildcard 302 file switches (ls-lisp-time-index switches)
313 (setq wildcard-regexp 303 wildcard-regexp full-directory-p)
314 (if ls-lisp-support-shell-wildcards 304 (invalid-regexp
315 (wildcard-to-regexp (file-name-nondirectory file)) 305 ;; Maybe they wanted a literal file that just happens to
316 (file-name-nondirectory file)) 306 ;; use characters special to shell wildcards.
317 file (file-name-directory file)) 307 (if (equal (cadr err) "Unmatched [ or [^")
318 (if (memq ?B switches) (setq wildcard-regexp "[^~]\\'"))) 308 (progn
319 (condition-case err 309 (setq wildcard-regexp (if (memq ?B switches) "[^~]\\'")
320 (ls-lisp-insert-directory 310 file (file-relative-name orig-file))
321 file switches (ls-lisp-time-index switches) 311 (ls-lisp-insert-directory
322 wildcard-regexp full-directory-p) 312 file switches (ls-lisp-time-index switches)
323 (invalid-regexp 313 nil full-directory-p))
324 ;; Maybe they wanted a literal file that just happens to 314 (signal (car err) (cdr err)))))))
325 ;; use characters special to shell wildcards.
326 (if (equal (cadr err) "Unmatched [ or [^")
327 (progn
328 (setq wildcard-regexp (if (memq ?B switches) "[^~]\\'")
329 file (file-relative-name orig-file))
330 (ls-lisp-insert-directory
331 file switches (ls-lisp-time-index switches)
332 nil full-directory-p))
333 (signal (car err) (cdr err)))))))))
334(advice-add 'insert-directory :around #'ls-lisp--insert-directory)
335 315
336(defun ls-lisp-insert-directory 316(defun ls-lisp-insert-directory
337 (file switches time-index wildcard-regexp full-directory-p) 317 (file switches time-index wildcard-regexp full-directory-p)
@@ -888,7 +868,6 @@ All ls time options, namely c, t and u, are handled."
888 868
889(defun ls-lisp-unload-function () 869(defun ls-lisp-unload-function ()
890 "Unload ls-lisp library." 870 "Unload ls-lisp library."
891 (advice-remove 'insert-directory #'ls-lisp--insert-directory)
892 (advice-remove 'dired #'ls-lisp--dired) 871 (advice-remove 'dired #'ls-lisp--dired)
893 ;; Continue standard unloading. 872 ;; Continue standard unloading.
894 nil) 873 nil)