diff options
| author | Stefan Monnier | 2023-12-09 23:45:56 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2023-12-09 23:45:56 -0500 |
| commit | 29957969e5199bdab5612af68e33b3989e4bbbd2 (patch) | |
| tree | 6f23a222835492c8332bbde55ed1ba3724b30c33 | |
| parent | f7cf85c3879c6857e8478bef41cce25a94759fb8 (diff) | |
| download | emacs-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.el | 21 | ||||
| -rw-r--r-- | lisp/files.el | 381 | ||||
| -rw-r--r-- | lisp/ls-lisp.el | 133 |
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\". |
| 121 | If nil, don't pass \"--dired\" to \"ls\". | 121 | If nil, don't pass \"--dired\" to \"ls\". |
| 122 | The special value of `unspecified' means to check whether \"ls\" | 122 | The special value of `unspecified' means to check whether |
| 123 | supports the \"--dired\" option, and save the result in this | 123 | `insert-directory-program' supports the \"--dired\" option, and save |
| 124 | variable. This is performed the first time `dired-insert-directory' | 124 | the result in this variable. |
| 125 | is invoked. (If `ls-lisp' is used by default, the test is performed | 125 | This is performed the first time `dired-insert-directory' |
| 126 | only if `ls-lisp-use-insert-directory-program' is non-nil, i.e., if | 126 | invokes `insert-directory-program'. |
| 127 | Dired actually uses \"ls\".) | ||
| 128 | 127 | ||
| 129 | Note that if you set this option to nil, either through choice or | 128 | Note that if you set this option to nil, either through choice or |
| 130 | because your \"ls\" program does not support \"--dired\", Dired | 129 | because 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'. | ||
| 7785 | Return 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. |
| 7785 | We assume the output has the format of `df'. | 7795 | We assume the output has the format of `df'. |
| @@ -7972,9 +7982,11 @@ Optional third arg WILDCARD means treat FILE as shell wildcard. | |||
| 7972 | Optional fourth arg FULL-DIRECTORY-P means file is a directory and | 7982 | Optional fourth arg FULL-DIRECTORY-P means file is a directory and |
| 7973 | switches do not contain `d', so that a full listing is expected. | 7983 | switches do not contain `d', so that a full listing is expected. |
| 7974 | 7984 | ||
| 7975 | This works by running a directory listing program | 7985 | Depending on the value of `ls-lisp-use-insert-directory-program' |
| 7976 | whose name is in the variable `insert-directory-program'. | 7986 | this works either using a Lisp emulation of the \"ls\" program |
| 7977 | If WILDCARD, it also runs the shell specified by `shell-file-name'. | 7987 | or by running a directory listing program |
| 7988 | whose name is in the variable `insert-directory-program' | ||
| 7989 | \(and if WILDCARD, it also runs the shell specified by `shell-file-name'). | ||
| 7978 | 7990 | ||
| 7979 | When SWITCHES contains the long `--dired' option, this function | 7991 | When SWITCHES contains the long `--dired' option, this function |
| 7980 | treats it specially, for the sake of dired. However, the | 7992 | treats 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. |
| 254 | Leaves point after the inserted text. | 254 | This implementation of `insert-directory' works using Lisp functions rather |
| 255 | SWITCHES may be a string of options, or a list of strings. | 255 | than `insert-directory-program'. |
| 256 | Optional third arg WILDCARD means treat FILE as shell wildcard. | 256 | |
| 257 | Optional fourth arg FULL-DIRECTORY-P means file is a directory and | 257 | This Lisp emulation does not run any external programs or shells. |
| 258 | switches do not contain `d', so that a full listing is expected. | 258 | It supports ordinary shell wildcards if `ls-lisp-support-shell-wildcards' |
| 259 | |||
| 260 | This version of the function comes from `ls-lisp.el'. | ||
| 261 | If the value of `ls-lisp-use-insert-directory-program' is non-nil then | ||
| 262 | this advice just delegates the work to ORIG-FUN (the normal `insert-directory' | ||
| 263 | function from `files.el'). | ||
| 264 | But if the value of `ls-lisp-use-insert-directory-program' is nil | ||
| 265 | then it runs a Lisp emulation. | ||
| 266 | |||
| 267 | The Lisp emulation does not run any external programs or shells. It | ||
| 268 | supports ordinary shell wildcards if `ls-lisp-support-shell-wildcards' | ||
| 269 | is non-nil; otherwise, it interprets wildcards as regular expressions | 259 | is non-nil; otherwise, it interprets wildcards as regular expressions |
| 270 | to match file names. It does not support all `ls' switches -- those | 260 | to match file names. It does not support all `ls' switches -- those |
| 271 | that 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 | 261 | that 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 |
| 272 | is assumed to be always present and cannot be turned off. | 262 | is assumed to be always present and cannot be turned off. |
| 273 | Long variants of the above switches, as documented for GNU `ls', | 263 | Long variants of the above switches, as documented for GNU `ls', |
| 274 | are also supported; unsupported long options are silently ignored." | 264 | are 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) |