[climacs-cvs] CVS climacs

dmurray dmurray at common-lisp.net
Sat May 6 11:41:57 UTC 2006


Update of /project/climacs/cvsroot/climacs
In directory clnet:/tmp/cvs-serv11198

Modified Files:
	file-commands.lisp 
Log Message:
Made local-options parsing a bit more robust, removed dependence
on split-sequence, and added command Reparse Attribute List
(a la Zmacs). Changed terminology from 'local options' to
'attribute line/list'.


--- /project/climacs/cvsroot/climacs/file-commands.lisp	2006/05/06 06:27:14	1.11
+++ /project/climacs/cvsroot/climacs/file-commands.lisp	2006/05/06 11:41:57	1.12
@@ -129,20 +129,8 @@
 	     :key #'climacs-syntax::syntax-description-pathname-types))
       'basic-syntax))
 
-(defun parse-local-options-line (line)
-  "Parse the local options line `line' and return an alist
-  mapping options to values. All option names will be coerced to
-  uppercase. `Line' must be stripped of the leading and
-  terminating -*- tokens."
-  (loop for pair in (split-sequence:split-sequence #\; line)
-     when (find #\: pair)
-     collect (destructuring-bind (key value)
-                 (loop for elem in (split-sequence:split-sequence #\: pair)
-                    collecting (string-trim " " elem))
-               (list (string-upcase key) value))))
-
-(defun evaluate-local-options (buffer options)
-  "Evaluate the local options `options' and modify `buffer' as
+(defun evaluate-attributes (buffer options)
+  "Evaluate the attributes `options' and modify `buffer' as
   appropriate. `Options' should be an alist mapping option names
   to their values."
   ;; First, check whether we need to change the syntax (via the SYNTAX
@@ -152,8 +140,8 @@
   (let ((specified-syntax
          (syntax-from-name
           (second (find-if #'(lambda (name)
-                               (or (string= name "SYNTAX")
-                                   (string= name "MODE")))
+                               (or (string-equal name "SYNTAX")
+                                   (string-equal name "MODE")))
                            options
                            :key #'first)))))
     (when specified-syntax
@@ -163,32 +151,74 @@
   ;; Now we iterate through the options (discarding SYNTAX and MODE
   ;; options).
   (loop for (name value) in options
-     unless (or (string= name "SYNTAX")
-                (string= name "MODE"))
+     unless (or (string-equal name "SYNTAX")
+                (string-equal name "MODE"))
      do (eval-option (syntax buffer) name value)))
 
-(defun evaluate-local-options-line (buffer)
-  "Evaluate the local options line of `buffer'. If `buffer' does
-  not have a local options line, this function is a no-op."
-  ;; This could be simplified a bit by using regexps.
-  (let* ((beginning-mark (beginning-of-buffer
-                          (clone-mark (point buffer))))
-         (end-mark (end-of-line (clone-mark beginning-mark)))
-         (line (buffer-sequence buffer (offset beginning-mark) (offset end-mark)))
-         (first-occurence (search "-*-" line))
-         (second-occurence
-          (when first-occurence
-            (search "-*-" line :start2 (1+ first-occurence)))))
-    (when (and first-occurence
-               second-occurence)
-      ;; Strip away the -*-s.
-      (let ((cleaned-options-line (coerce (subseq line
-                                                  (+ first-occurence 3)
-                                                  second-occurence)
-                                          'string)))
-        (evaluate-local-options
-         buffer
-         (parse-local-options-line cleaned-options-line))))))
+(defun split-attribute (string char)
+  (let (pairs)
+    (loop with start = 0
+	  for ch across string
+	  for i from 0
+	  when (eql ch char)
+	    do (push (string-trim '(#\Space #\Tab) (subseq string start i))
+		     pairs)
+	       (setf start (1+ i))
+	  finally (unless (>= start i)
+		    (push (string-trim '(#\Space #\Tab) (subseq string start))
+			  pairs)))
+    (nreverse pairs)))
+
+(defun split-attribute-line (line)
+  (mapcar (lambda (pair) (split-attribute pair #\:))
+	  (split-attribute line #\;)))
+
+(defun get-attribute-line (buffer)
+  (let ((scan (beginning-of-buffer (clone-mark (point buffer)))))
+    ;; skip the leading whitespace
+    (loop until (end-of-buffer-p scan)
+	  until (not (whitespacep (object-after scan)))
+	  do (forward-object scan))
+    ;; stop looking if we're already 1,000 objects into the buffer
+    (unless (> (offset scan) 1000)
+      (let ((start-found
+	     (loop with newlines = 0
+		   when (end-of-buffer-p scan)
+		     do (return nil)
+		   when (eql (object-after scan) #\Newline)
+		     do (incf newlines)
+		   when (> newlines 1)
+		     do (return nil)
+		   do (forward-object scan)
+		   until (looking-at scan "-*-")
+		   finally (return t))))
+	(when start-found
+	  (let ((line (buffer-substring buffer
+					(offset scan)
+					(offset (end-of-line (clone-mark scan))))))
+	    (when (>= (length line) 6)
+	      (let ((end (search "-*-" line :from-end t :start2 3)))
+		(when end
+		  (string-trim '(#\Space #\Tab) (subseq line 3 end)))))))))))
+
+(defun evaluate-attributes-line (buffer)
+  (evaluate-attributes
+   buffer
+   (split-attribute-line (get-attribute-line buffer))))
+
+(define-command (com-reparse-attribute-list :name t :command-table buffer-table) ()
+  "Reparse the current buffer's attribute list.
+An attribute list is a line of keyword-value pairs, each keyword separated
+from the corresponding value by a colon. If another keyword-value pair
+follows, the value should be terminated by a colon. The attribute list
+is surrounded by '-*-' sequences, but the opening '-*-' need not be at the
+beginning of the line. Climacs looks for the attribute list
+on the first or second non-blank line of the file.
+
+An example attribute-list is:
+
+;; -*- Syntax: Lisp; Base: 10 -*- "
+  (evaluate-attributes-line (buffer (current-window))))
 
 ;; Adapted from cl-fad/PCL
 (defun directory-pathname-p (pathspec)




More information about the Climacs-cvs mailing list