(provide 'tools)

(defun flatten (lst)
  (let ((left lst)
	(out '()))
    (while (not (null left))
      (let ((first (car left)))
	(if (atom first)
	    (setq out (append out (list first)))
	  (setq out (append out (flatten first)))))
      (setq left (cdr left)))
    out))

;;; This is Barr3y's split code, stolen from zwgc.

(provide 'split)

(defun split (string &optional regexp sep)
  "Splits STRING into a list of strings by choosing breakpoints 
according to REGEXP.  If REGEXP does not occur the entire STRING
is contained in the first element of the returned list.  REGEXP is
optional and defaults to [ \\t]+ (whitespace).  Optional third arg
SEPARATORS causes the text that matches grouped expressions in REGEXP
at each breakpoint to be included in the returned list.  WARNING: This
function can loop endlessly if REGEXP matches the null string."
  (if regexp nil (setq regexp "[ \t]+"))
  (let ((buf (generate-new-buffer "  *tmp")))
    (unwind-protect 
	(save-excursion
	  (let* ((split-list (list 'split-list))
		 (split-tail (last split-list)))
	    (set-buffer buf)
	    (insert string)
	    (goto-char (point-min))
	    (let ((p (point)))
	      (while (re-search-forward regexp nil t)
		(setcdr split-tail
			(list (buffer-substring p (match-beginning 0))))
		(setq split-tail (cdr split-tail))
		(setq mtext (matched-strings))
		(if (and sep mtext)
		    (progn
		      (setcdr split-tail (list mtext))
		      (setq split-tail (cdr split-tail))))
		(setq p (point))))
	    (setcdr split-tail (list (buffer-substring (point) (point-max))))
	    (setq split-tail (cdr split-tail))
	    (cdr split-list)))
      (kill-buffer buf))))

(defun matched-strings-list ()
  "Returns a list that contains each grouped subexpression matched in
the previous regular-expression search."
  (interactive)
  ;; Skip the first pair of numbers since it is the ENTIRE matched string.
  (let* ((data (cddr (match-data)))
	(mlist (list 'mlist))
	(mtail (last mlist)))
    (while data
      (if (car data)
	  (progn
	    (setcdr mtail (list (buffer-substring (car data) (cadr data))))
	    (setq mtail (cdr mtail))))
      (setq data (cddr data)))
    (cdr mlist)))

(defun matched-strings ()
  "Returns a single string that is the concatenation of all the parenthesized
expressions in the previous regular-expression search."
  (interactive)
  (apply 'concat (matched-strings-list)))

(defun cddr (c) "Returns (cdr (cdr x))." (cdr (cdr c)))

(defun last (lst)
  "Return the pointer to last element of LIST or nil is LIST is nil.
(setcdr (last l) (cons NEW-ELEMENT nil)) appends NEW-ELEMENT to the 
end of l via mutation."
  (nthcdr (1- (length lst)) lst))
