;;; hash-csv.l ;;; Ver.1.0.3.20110119 ;;; 2006-12-21, 2011-01-19 ;;; Public Domain ;;; http://purl.com/net/dkcc/shed/hash-table-to-csv.html (provide "hash-csv") (in-package "editor") (export '(hash-table-to-csv hash-table-all-entries count-chars)) (defun hash-table-to-csv (table &key (quotes t) (princ t) (header "key,val") (output-buffer "*hash-csv*") &aux (field-string (if princ "~A" "~S")) output-string so) "Convert hash table into csv in *hash-csv* buffer. This csv format may conform to RFC 4180. It means every double-quotes are automatically escaped by another double-quotes. Usage: (hash-table-to-csv table :quotes nil :princ nil :header \"No.,key,val\" :output-buffer \"*hash2csv*\") quotes: When t, each field is enclosed in double-quotes. Even if nil, fields which contain commas, line breaks or double-quotes are enclosed in double-quotes. princ: Print type of each field. When t, print type is ~A. When nil, ~S. header: The first line of csv. header must contains one comma (= two fields). You can also set header nil to omit the header line. output-buffer: The name of output buffer. When nil, output will go to *standard-output*. Note: When a field contains commas, line breaks or double-quotes, you should set quote t for a valid format." (interactive "Shash-table: ") (when (symbolp table) (setq table (eval table))) (if (null output-buffer) (setq so *standard-output*) (progn (unless (prog1 (find-buffer output-buffer) (setq so (make-buffer-stream (switch-to-buffer output-buffer)))) (make-local-variable 'need-not-save) (setq need-not-save t) (when (find-symbol "csv-mode" "editor") (csv-mode))) (delete-region (point-min) (point-max)))) ;;; (with-output-to-selected-buffer ;;; (with-output-to-temp-buffer (bo nil) (when header (format so "~A~%" header)) (maphash (lambda (key val) (format so "~{~A~^,~}~%" ; "~A" is needed because output-string may contain control string (mapcar (lambda (field) (setq output-string (quote-string (format nil field-string field) #\" #\")) (if (or quotes (string-match "[\",\n]" output-string)) (concat "\"" output-string "\"") output-string)) (list key val)))) table) so) ;;; e.g. (hash-table-to-csv *ss-ghost-table*) (defun hash-table-all-entries (table &key (quotes t) (princ t)) "Print all keys and values of a hash table." (hash-table-to-csv table :quotes quotes :princ princ :output-buffer nil)) (defun count-chars (&key (input-buffer (selected-buffer)) (point (point-min)) (output-buffer "*count-chars*") quotes) "Count characters in the current buffer." (interactive) (save-excursion (long-operation (with-input-from-buffer (input-buffer point) (let ((count (make-hash-table)) char) (while (setq char (read-char *standard-input* nil)) (if (gethash char count) (incf (gethash char count)) (setf (gethash char count) 1))) (hash-table-to-csv count :princ nil :header (concat "\"" (buffer-name (selected-buffer)) "\",\"char-counts\"") :output-buffer output-buffer :quotes quotes)))))) ;;; elapsed time [http://daukan.hp.infoseek.co.jp/program/outtest5-sjis.txt]: raw: 318.422s, byte-compiled: 2.454s