From 2ed12c5bce861ecb3fd5964f719fc48ab7b20cc2 Mon Sep 17 00:00:00 2001 From: Brit Butler Date: Wed, 3 Sep 2014 14:34:53 -0400 Subject: [PATCH] Factor out parse-metadata in preparation for real error-handling. --- docs/hacking.md | 2 +- src/content.lisp | 34 +++++++++++++++++++--------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/docs/hacking.md b/docs/hacking.md index 9d31492..8e32cc5 100644 --- a/docs/hacking.md +++ b/docs/hacking.md @@ -248,7 +248,7 @@ at best, especially for anyone not coming from the lisp world. We need to start handling errors and reporting errors in ways that are useful to the user. Example errors users have encountered: -1. Loading of Content. If `read-content` fails to parse a file, wen +1. Loading of Content. If `read-content` fails to parse a file, we should tell the user what file failed and why. We also should probably enforce more constraints about metadata. E.g. Empty metadata is not allowed/meaningful. Trailing space after separator, etc. diff --git a/src/content.lisp b/src/content.lisp index 7b40945..2033e48 100644 --- a/src/content.lisp +++ b/src/content.lisp @@ -48,27 +48,31 @@ (when (stringp tags) (setf tags (mapcar #'make-tag (cl-ppcre:split "," tags)))))) +(defun parse-metadata (stream) + "Given a STREAM, parse metadata from it or signal an appropriate condition." + (flet ((parse-field (str) + (nth-value 1 (cl-ppcre:scan-to-strings "[a-zA-Z]+:\\s+(.*)" str))) + (field-name (line) + (make-keyword (string-upcase (subseq line 0 (position #\: line)))))) + (unless (string= (read-line stream nil) (separator *config*)) + (error "The provided file lacks the expected header.")) + (loop for line = (read-line stream nil) + until (string= line (separator *config*)) + appending (list (field-name line) + (aref (parse-field line) 0))))) + (defun read-content (file) - "Returns a plist of metadata from FILE with :text holding the content as a string." + "Returns a plist of metadata from FILE with :text holding the content." (flet ((slurp-remainder (stream) (let ((seq (make-string (- (file-length stream) (file-position stream))))) (read-sequence seq stream) - (remove #\Nul seq))) - (parse-field (str) - (nth-value 1 (cl-ppcre:scan-to-strings "[a-zA-Z]+:\\s+(.*)" str))) - (field-name (line) - (make-keyword (string-upcase (subseq line 0 (position #\: line)))))) + (remove #\Nul seq)))) (with-open-file (in file :external-format '(:utf-8)) - (unless (string= (read-line in) (separator *config*)) - (error "The provided file lacks the expected header.")) - (let ((meta (loop for line = (read-line in nil) - until (string= line (separator *config*)) - appending (list (field-name line) - (aref (parse-field line) 0)))) - (filepath (enough-namestring file (repo *config*))) - (content (slurp-remainder in))) - (append meta (list :text content :file filepath)))))) + (let ((metadata (parse-metadata in)) + (content (slurp-remainder in)) + (filepath (enough-namestring file (repo *config*)))) + (append metadata (list :text content :file filepath)))))) ;; Helper Functions