Function: insert-directory

insert-directory is a byte-compiled function defined in files.el.gz.

Signature

(insert-directory FILE SWITCHES &optional WILDCARD FULL-DIRECTORY-P)

Documentation

Insert directory listing for FILE, formatted according to SWITCHES.

Leaves point after the inserted text. SWITCHES may be a string of options, or a list of strings representing individual options. Optional third arg WILDCARD means treat FILE as shell wildcard. Optional fourth arg FULL-DIRECTORY-P means file is a directory and switches do not contain d, so that a full listing is expected.

Depending on the value of ls-lisp-use-insert-directory-program this works either using a Lisp emulation of the "ls" program or by running a directory listing program whose name is in the variable insert-directory-program
(and if WILDCARD, it also runs the shell specified by shell-file-name).

When SWITCHES contains the long --dired option, this function treats it specially, for the sake of dired. However, the normally equivalent short -D option is just passed on to insert-directory-program, as any other option.

View in manual

Probably introduced at or before Emacs version 20.1.

Source Code

;; Defined in /usr/src/emacs/lisp/files.el.gz
;; insert-directory
;; - must insert _exactly_one_line_ describing FILE if WILDCARD and
;;   FULL-DIRECTORY-P is nil.
;;   The single line of output must display FILE's name as it was
;;   given, namely, an absolute path name.
;; - must insert exactly one entry for each file if WILDCARD or
;;   FULL-DIRECTORY-P is t, plus one optional "total" line
;;   before the file lines, plus optional text after the file lines.
;;   Entries are delimited by "\n", but file names containing "\n" are
;;   allowed and by default the "\n" is displayed as a literal newline.
;;   File entries should display the basename.
;; - must be consistent with
;;   - functions dired-move-to-filename, (these two define what a file line is)
;;               dired-move-to-end-of-filename,
;;		 dired-between-files, (shortcut for (not (dired-move-to-filename)))
;;               dired-insert-headerline
;;               dired-after-subdir-garbage (defines what a "total" line is)
;;   - variable dired-subdir-regexp
;; - may be passed "--dired" as the first argument in SWITCHES.
;;   File name handlers might have to remove this switch if their
;;   "ls" command does not support it.
(defun insert-directory (file switches &optional wildcard full-directory-p)
  "Insert directory listing for FILE, formatted according to SWITCHES.
Leaves point after the inserted text.
SWITCHES may be a string of options, or a list of strings
representing individual options.
Optional third arg WILDCARD means treat FILE as shell wildcard.
Optional fourth arg FULL-DIRECTORY-P means file is a directory and
switches do not contain `d', so that a full listing is expected.

Depending on the value of `ls-lisp-use-insert-directory-program'
this works either using a Lisp emulation of the \"ls\" program
or by running a directory listing program
whose name is in the variable `insert-directory-program'
\(and if WILDCARD, it also runs the shell specified by `shell-file-name').

When SWITCHES contains the long `--dired' option, this function
treats it specially, for the sake of dired.  However, the
normally equivalent short `-D' option is just passed on to
`insert-directory-program', as any other option."
  ;; We need the directory in order to find the right handler.
  (let ((handler (find-file-name-handler (expand-file-name file)
					 'insert-directory)))
    (cond
     (handler
      (funcall handler 'insert-directory file switches
	       wildcard full-directory-p))
     ((not (files--use-insert-directory-program-p))
      (require 'ls-lisp)
      (declare-function ls-lisp--insert-directory "ls-lisp")
      (ls-lisp--insert-directory file switches wildcard full-directory-p))
     (t
      (let ((beg (point))
            (errfile (make-temp-file "lserr")))

	;; Read the actual directory using `insert-directory-program'.
	(let* (;; We at first read by no-conversion, then after
	       ;; putting text property `dired-filename, decode one
	       ;; bunch by one to preserve that property.
	       (coding-system-for-read 'no-conversion)
	       ;; This is to control encoding the arguments in call-process.
	       (coding-system-for-write
		(and enable-multibyte-characters
		     (or file-name-coding-system
			 default-file-name-coding-system))))
	  (if wildcard
	      ;; If the wildcard is just in the file part, then run ls in
              ;; the directory part of the file pattern using the last
              ;; component as argument.  Otherwise, run ls in the longest
              ;; subdirectory of the directory part free of wildcards; use
              ;; the remaining of the file pattern as argument.
	      (let* ((dir-wildcard
                      (insert-directory-wildcard-in-dir-p file))
                     (default-directory
                      (cond (dir-wildcard (car dir-wildcard))
                            (t
			     (if (file-name-absolute-p file)
				 (file-name-directory file)
			       (file-name-directory
                                (expand-file-name file))))))
		     (pattern (if dir-wildcard
                                  (cdr dir-wildcard)
                                (file-name-nondirectory file))))
		;; NB since switches is passed to the shell, be
		;; careful of malicious values, eg "-l;reboot".
		;; See eg dired-safe-switches-p.
		(call-process
		 shell-file-name nil (list t errfile) nil
		 shell-command-switch
		 (concat (if (memq system-type '(ms-dos windows-nt))
			     ""
			   "\\") ; Disregard Unix shell aliases!
			 insert-directory-program
			 " -d "
			 ;; Quote switches that require quoting
			 ;; such as "--block-size='1".  But don't
			 ;; quote switches that use patterns
			 ;; such as "--ignore=PATTERN" (bug#71935).
			 (mapconcat #'shell-quote-wildcard-pattern
				    (if (stringp switches)
					(split-string-and-unquote switches)
				      switches)
				    " ")
			 " -- "
			 ;; Quote some characters that have
			 ;; special meanings in shells; but
			 ;; don't quote the wildcards--we want
			 ;; them to be special.  We also
			 ;; currently don't quote the quoting
			 ;; characters in case people want to
			 ;; use them explicitly to quote
			 ;; wildcard characters.
			 (shell-quote-wildcard-pattern pattern))))
	    ;; SunOS 4.1.3, SVr4 and others need the "." to list the
	    ;; directory if FILE is a symbolic link.
	    (unless full-directory-p
	      (setq switches
		    (cond
                     ((stringp switches) (concat switches " -d"))
                     ((member "-d" switches) switches)
                     (t (append switches '("-d"))))))
	    (if (string-match "\\`~" file)
		(setq file (expand-file-name file)))
	    (apply #'call-process
		   insert-directory-program nil (list t errfile) nil
		   (append
		    (if (listp switches) switches
		      (unless (equal switches "")
			;; Split the switches at any spaces so we can
			;; pass separate options as separate args.
			(split-string-and-unquote switches)))
		    ;; Avoid lossage if FILE starts with `-'.
		    '("--")
		    (list file)))))

        ;; If `ls' emits an error message, copy it to a buffer that will
        ;; be displayed when a Dired invocation results in the `ls'
        ;; error.
        (when (> (file-attribute-size (file-attributes errfile)) 0)
          (defvar dired--ls-error-buffer) ; Pacify byte-compiler.
          (let ((errbuf (get-buffer-create "*ls error*")))
            (with-current-buffer errbuf
              (erase-buffer)
              (insert-file-contents errfile))
            (setq dired--ls-error-buffer errbuf)))
        (defvar dired--ls-error-file) ; Pacify byte-compiler.
        (setq dired--ls-error-file errfile)
        (delete-file errfile)

        (insert-directory-clean beg switches)
	;; Now decode what read if necessary.
	(let ((coding (or coding-system-for-read
			  file-name-coding-system
			  default-file-name-coding-system
			  'undecided))
	      coding-no-eol
	      val pos)
	  (when (and enable-multibyte-characters
		     (not (memq (coding-system-base coding)
				'(raw-text no-conversion))))
	    ;; If no coding system is specified or detection is
	    ;; requested, detect the coding.
	    (if (eq (coding-system-base coding) 'undecided)
		(setq coding (detect-coding-region beg (point) t)))
	    (if (not (eq (coding-system-base coding) 'undecided))
		(save-restriction
		  (setq coding-no-eol
			(coding-system-change-eol-conversion coding 'unix))
		  (narrow-to-region beg (point))
		  (goto-char (point-min))
		  (while (not (eobp))
		    (setq pos (point)
			  val (get-text-property (point) 'dired-filename))
		    (goto-char (next-single-property-change
				(point) 'dired-filename nil (point-max)))
		    ;; Force no eol conversion on a file name, so
		    ;; that CR is preserved.
		    (decode-coding-region pos (point)
					  (if val coding-no-eol coding))
		    (if val
			(put-text-property pos (point)
					   'dired-filename t))))))))))))