their elements).
@end defun
+@defun flatten-tree tree
+Take @var{tree} and "flatten" it.
+This always returns a list containing all the terminal nodes, or
+leaves, of @var{tree}. Dotted pairs are flattened as well, and nil
+elements are removed.
+@end defun
+
+@example
+(flatten-tree '(1 (2 . 3) nil (4 5 (6)) 7))
+ @result{}(1 2 3 4 5 6 7)
+@end example
+
@defun number-sequence from &optional to separation
This returns a list of numbers starting with @var{from} and
incrementing by @var{separation}, and ending at or just before
** New function 'ring-resize'.
'ring-resize' can be used to grow or shrink a ring.
++++
+** New function 'flatten-tree'.
+'flatten-list' is provided as an alias. These functions take a tree
+and 'flatten' it such that the result is a list of all the terminal
+nodes.
+
** Mailcap
---
(defun eshell/printnl (&rest args)
"Print out each of the arguments, separated by newlines."
- (let ((elems (eshell-flatten-list args)))
+ (let ((elems (flatten-tree args)))
(while elems
(eshell-printn (eshell-echo (list (car elems))))
(setq elems (cdr elems)))))
(if (> (length args) 1)
(error "%s: command not found" (car args))
(throw 'eshell-replace-command
- (eshell-parse-command "cd" (eshell-flatten-list args)))))
+ (eshell-parse-command "cd" (flatten-tree args)))))
(defun eshell-parse-user-reference ()
"An argument beginning with ~ is a filename to be expanded."
(defun eshell/cd (&rest args) ; all but first ignored
"Alias to extend the behavior of `cd'."
- (setq args (eshell-flatten-list args))
+ (setq args (flatten-tree args))
(let ((path (car args))
(subpath (car (cdr args)))
(case-fold-search (eshell-under-windows-p))
(let* (eshell-interpreter-alist
(interp (eshell-find-interpreter (car args) (cdr args)))
(program (car interp))
- (args (eshell-flatten-list
+ (args (flatten-tree
(eshell-stringify-list (append (cdr interp)
(cdr args)))))
(term-buf
"Alias \"su\" to call TRAMP.
Uses the system su through TRAMP's su method."
- (setq args (eshell-stringify-list (eshell-flatten-list args)))
+ (setq args (eshell-stringify-list (flatten-tree args)))
(let ((orig-args (copy-tree args)))
(eshell-eval-using-options
"su" args
"Alias \"sudo\" to call Tramp.
Uses the system sudo through TRAMP's sudo method."
- (setq args (eshell-stringify-list (eshell-flatten-list args)))
+ (setq args (eshell-stringify-list (flatten-tree args)))
(let ((orig-args (copy-tree args)))
(eshell-eval-using-options
"sudo" args
This is implemented to call either `delete-file', `kill-buffer',
`kill-process', or `unintern', depending on the nature of the
argument."
- (setq args (eshell-flatten-list args))
+ (setq args (flatten-tree args))
(eshell-eval-using-options
"rm" args
'((?h "help" nil nil "show this usage screen")
(error "%s: missing destination file or directory" ,command))
(if (= len 1)
(nconc args '(".")))
- (setq args (eshell-stringify-list (eshell-flatten-list args)))
+ (setq args (eshell-stringify-list (flatten-tree args)))
(if (and ,(not (equal command "ln"))
(string-match eshell-tar-regexp (car (last args)))
(or (> (length args) 2)
"Implementation of cat in Lisp.
If in a pipeline, or the file is not a regular file, directory or
symlink, then revert to the system's definition of cat."
- (setq args (eshell-stringify-list (eshell-flatten-list args)))
+ (setq args (eshell-stringify-list (flatten-tree args)))
(if (or eshell-in-pipeline-p
(catch 'special
(dolist (arg args)
(compile (concat "make " (eshell-flatten-and-stringify args))))
(throw 'eshell-replace-command
(eshell-parse-command "*make" (eshell-stringify-list
- (eshell-flatten-list args))))))
+ (flatten-tree args))))))
(put 'eshell/make 'eshell-no-numeric-conversions t)
(erase-buffer)
(occur-mode)
(let ((files (eshell-stringify-list
- (eshell-flatten-list (cdr args))))
+ (flatten-tree (cdr args))))
(inhibit-redisplay t)
string)
(when (car args)
(throw 'eshell-replace-command
(eshell-parse-command (concat "*" command)
(eshell-stringify-list
- (eshell-flatten-list args))))
+ (flatten-tree args))))
(let* ((args (mapconcat 'identity
(mapcar 'shell-quote-argument
(eshell-stringify-list
- (eshell-flatten-list args)))
+ (flatten-tree args)))
" "))
(cmd (progn
(set-text-properties 0 (length args)
(defun eshell/du (&rest args)
"Implementation of \"du\" in Lisp, passing ARGS."
(setq args (if args
- (eshell-stringify-list (eshell-flatten-list args))
+ (eshell-stringify-list (flatten-tree args))
'(".")))
(let ((ext-du (eshell-search-path "du")))
(if (and ext-du
(eshell-parse-command (car time-args)
;;; https://lists.gnu.org/r/bug-gnu-emacs/2007-08/msg00205.html
(eshell-stringify-list
- (eshell-flatten-list (cdr time-args))))))))
+ (flatten-tree (cdr time-args))))))))
(defun eshell/whoami (&rest _args)
"Make \"whoami\" Tramp aware."
(defun eshell/diff (&rest args)
"Alias \"diff\" to call Emacs `diff' function."
- (let ((orig-args (eshell-stringify-list (eshell-flatten-list args))))
+ (let ((orig-args (eshell-stringify-list (flatten-tree args))))
(if (or eshell-plain-diff-behavior
(not (and (eshell-interactive-output-p)
(not eshell-in-pipeline-p)
(string-match "^-" (car args))))
(throw 'eshell-replace-command
(eshell-parse-command "*locate" (eshell-stringify-list
- (eshell-flatten-list args))))
+ (flatten-tree args))))
(save-selected-window
(let ((locate-history-list (list (car args))))
(locate-with-filter (car args) (cadr args))))))
"Implementation of expr, using the calc package."
(if (not (fboundp 'calc-eval))
(throw 'eshell-replace-command
- (eshell-parse-command "*expr" (eshell-flatten-list args)))
+ (eshell-parse-command "*expr" (flatten-tree args)))
;; to fool the byte-compiler...
(let ((func 'calc-eval))
(funcall func (eshell-flatten-and-stringify args)))))
(defun eshell-external-command (command args)
"Insert output from an external COMMAND, using ARGS."
- (setq args (eshell-stringify-list (eshell-flatten-list args)))
+ (setq args (eshell-stringify-list (flatten-tree args)))
(let ((interp (eshell-find-interpreter
command
args
arguments.
:preserve-args
- If present, do not pass MACRO-ARGS through `eshell-flatten-list'
+ If present, do not pass MACRO-ARGS through `flatten-tree'
and `eshell-stringify-list'.
:parse-leading-options-only
,(if (memq ':preserve-args (cadr options))
macro-args
(list 'eshell-stringify-list
- (list 'eshell-flatten-list macro-args))))
+ (list 'flatten-tree macro-args))))
(processed-args (eshell--do-opts ,name ,options temp-args))
,@(delete-dups
(delq nil (mapcar (lambda (opt)
,@forms)
(setq list-iter (cdr list-iter)))))
-(defun eshell-flatten-list (args)
- "Flatten any lists within ARGS, so that there are no sublists."
- (let ((new-list (list t)))
- (dolist (a args)
- (if (and (listp a)
- (listp (cdr a)))
- (nconc new-list (eshell-flatten-list a))
- (nconc new-list (list a))))
- (cdr new-list)))
+(define-obsolete-function-alias 'eshell-flatten-list #'flatten-tree "27.1")
(defun eshell-uniquify-list (l)
"Remove occurring multiples in L. You probably want to sort first."
(defsubst eshell-flatten-and-stringify (&rest args)
"Flatten and stringify all of the ARGS into a single string."
- (mapconcat 'eshell-stringify (eshell-flatten-list args) " "))
+ (mapconcat 'eshell-stringify (flatten-tree args) " "))
(defsubst eshell-directory-files (regexp &optional directory)
"Return a list of files in the given DIRECTORY matching REGEXP."
(let (headers thread last-id)
;; First go up in this thread until we find the root.
(setq last-id (gnus-root-id id)
- headers (message-flatten-list (gnus-id-to-thread last-id)))
+ headers (flatten-tree (gnus-id-to-thread last-id)))
;; We have now found the real root of this thread. It might have
;; been gathered into some loose thread, so we have to search
;; through the threads to find the thread we wanted.
"Return the highest article number in THREAD."
(apply 'max (mapcar (lambda (header)
(mail-header-number header))
- (message-flatten-list thread))))
+ (flatten-tree thread))))
(defun gnus-article-sort-by-most-recent-date (h1 h2)
"Sort articles by number."
"Return the highest article date in THREAD."
(apply 'max
(mapcar (lambda (header) (float-time
- (gnus-date-get-time
- (mail-header-date header))))
- (message-flatten-list thread))))
+ (gnus-date-get-time
+ (mail-header-date header))))
+ (flatten-tree thread))))
(defun gnus-thread-total-score-1 (root)
;; This function find the total score of the thread below ROOT.
If SHOW is non-nil, the arguments TEXT... are displayed in a temp buffer.
The following arguments may contain lists of values."
(if (and show
- (setq text (message-flatten-list text)))
+ (setq text (flatten-tree text)))
(save-window-excursion
(with-output-to-temp-buffer " *MESSAGE information message*"
(with-current-buffer " *MESSAGE information message*"
(funcall ask question))
(funcall ask question)))
-(defun message-flatten-list (list)
- "Return a new, flat list that contains all elements of LIST.
-
-\(message-flatten-list \\='(1 (2 3 (4 5 (6))) 7))
-=> (1 2 3 4 5 6 7)"
- (cond ((consp list)
- (apply 'append (mapcar 'message-flatten-list list)))
- (list
- (list list))))
+(define-obsolete-function-alias 'message-flatten-list #'flatten-tree "27.1")
(defun message-generate-new-buffer-clone-locals (name &optional varstr)
"Create and return a buffer with name based on NAME using `generate-new-buffer'.
(insert "\n--" boundary "--\n")))
(defun nnimap-find-wanted-parts (structure)
- (message-flatten-list (nnimap-find-wanted-parts-1 structure "")))
+ (flatten-tree (nnimap-find-wanted-parts-1 structure "")))
(defun nnimap-find-wanted-parts-1 (structure prefix)
(let ((num 1)
(defun lpr-print-region (start end switches name)
(let ((buf (current-buffer))
- (nswitches (lpr-flatten-list
+ (nswitches (flatten-tree
(mapcar #'lpr-eval-switch ; Dynamic evaluation
switches)))
(switch-string (if switches
((consp arg) (apply (car arg) (cdr arg)))
(t nil)))
-;; `lpr-flatten-list' is defined here (copied from "message.el" and
-;; enhanced to handle dotted pairs as well) until we can get some
-;; sensible autoloads, or `flatten-list' gets put somewhere decent.
-
-;; (lpr-flatten-list '((a . b) c (d . e) (f g h) i . j))
-;; => (a b c d e f g h i j)
-
-(defun lpr-flatten-list (&rest list)
- (lpr-flatten-list-1 list))
-
-(defun lpr-flatten-list-1 (list)
- (cond
- ((null list) nil)
- ((consp list)
- (append (lpr-flatten-list-1 (car list))
- (lpr-flatten-list-1 (cdr list))))
- (t (list list))))
+(define-obsolete-function-alias 'lpr-flatten-list #'flatten-tree "27.1")
(provide 'lpr)
(defun pr-switches (switches mess)
(or (listp switches)
(error "%S should have a list of strings" mess))
- (lpr-flatten-list ; dynamic evaluation
+ (flatten-tree ; dynamic evaluation
(mapcar #'lpr-eval-switch switches)))
"Parse state at `js--last-parse-pos'.")
(make-variable-buffer-local 'js--state-at-last-parse-pos)
-(defun js--flatten-list (list)
- (cl-loop for item in list
- nconc (cond ((consp item)
- (js--flatten-list item))
- (item (list item)))))
+(define-obsolete-function-alias 'js--flatten-list #'flatten-tree "27.1")
(defun js--maybe-join (prefix separator suffix &rest list)
"Helper function for `js--update-quick-match-re'.
with SUFFIX as with `concat'. Otherwise, if LIST is empty, return
nil. If any element in LIST is itself a list, flatten that
element."
- (setq list (js--flatten-list list))
+ (setq list (flatten-tree list))
(when list
(concat prefix (mapconcat #'identity list separator) suffix)))
(setq file (concat (substring file 1 2) ":" (substring file 2))))
file)
+(defun flatten-tree (tree)
+ "Take TREE and \"flatten\" it.
+This always returns a list containing all the terminal nodes, or
+\"leaves\", of TREE. Dotted pairs are flattened as well, and nil
+elements are removed.
+
+\(flatten-tree \\='(1 (2 . 3) nil (4 5 (6)) 7))
+=> (1 2 3 4 5 6 7)
+
+TREE can be anything that can be made into a list. For each
+element in TREE, if it is a cons cell return its car
+recursively. Otherwise return the element."
+ (let (elems)
+ (setq tree (list tree))
+ (while (let ((elem (pop tree)))
+ (cond ((consp elem)
+ (setq tree (cons (car elem) (cons (cdr elem) tree))))
+ (elem
+ (push elem elems)))
+ tree))
+ (nreverse elems)))
+
+;; Technically, `flatten-list' is a misnomer, but we provide it here
+;; for discoverability:
+(defalias 'flatten-list 'flatten-tree)
;;; subr.el ends here
(shell-quote-argument "%ca%")))
"without-caret %ca%"))))
+(ert-deftest subr-tests-flatten-tree ()
+ "Test `flatten-tree' behavior."
+ (should (equal (flatten-tree '(1 (2 . 3) nil (4 5 (6)) 7))
+ '(1 2 3 4 5 6 7)))
+ (should (equal (flatten-tree '((1 . 2)))
+ '(1 2)))
+ (should (equal (flatten-tree '(1 nil 2))
+ '(1 2)))
+ (should (equal (flatten-tree 42)
+ '(42)))
+ (should (equal (flatten-tree t)
+ '(t)))
+ (should (equal (flatten-tree nil)
+ nil))
+ (should (equal (flatten-tree '(1 ("foo" "bar") 2))
+ '(1 "foo" "bar" 2))))
+
(provide 'subr-tests)
;;; subr-tests.el ends here