f36b8fd3e9dd

Clean up symbol parsing so `foo::bar` works properly
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sun, 21 Aug 2016 12:21:26 +0000
parents 2b76060dba22
children e342c4a78a57
branches/tags (none)
files package.lisp src/middleware/documentation.lisp src/utils.lisp

Changes

--- a/package.lisp	Sun Aug 21 12:04:31 2016 +0000
+++ b/package.lisp	Sun Aug 21 12:21:26 2016 +0000
@@ -1,9 +1,9 @@
-;;;; package.lisp
-
 (defpackage #:nrepl
-  (:use #:cl)
+  (:use
+    #:cl
+    #:split-sequence)
   (:import-from :ppcre
-                :regex-replace)
+    :regex-replace)
   (:export #:start-server
-           #:stop-server))
+    #:stop-server))
 
--- a/src/middleware/documentation.lisp	Sun Aug 21 12:04:31 2016 +0000
+++ b/src/middleware/documentation.lisp	Sun Aug 21 12:21:26 2016 +0000
@@ -20,33 +20,59 @@
       t)
     (values nil nil)))
 
-(defun find-symbol-harder (name &optional in-package)
-  "Return the symbol object with the given `name`.
+
+(defun parse-symbol-designator-package (string in-package)
+  (let ((parts (split-sequence-if (partial #'char= #\:)
+                                  (string-upcase string))))
+    (case (length parts)
+      (0 nil)
+
+      ;; FOO -> ("FOO")
+      (1 (parse-in-package in-package))
+
+      ;; :FOO -> ("" "FOO")
+      ;; P:FOO -> ("P" "FOO")
+      (2 (if (string= (first parts) "")
+           (find-package "KEYWORD")
+           (parse-in-package in-package)))
+
+      ;; P::FOO -> ("P" "" "FOO")
+      (3 (find-package (first parts)))
+      (t nil))))
+
+(defun parse-symbol-designator-name (string)
+  (let ((parts (split-sequence-if (partial #'char= #\:)
+                                  (string-upcase string))))
+    (case (length parts)
+      (0 nil)
+
+      ;; FOO -> ("FOO")
+      (1 (first parts))
+
+      ;; :FOO -> ("" "FOO")
+      ;; P:FOO -> ("P" "FOO")
+      (2 (second parts))
+
+      ;; P::FOO -> ("P" "" "FOO")
+      (3 (third parts))
+
+      (t nil))))
+
+(defun find-symbol-harder (symbol-designator &optional in-package)
+  "Return the symbol object with the given `symbol-designator`.
 
   This should work with names like:
 
-    FOO (assumes the current package)
+    FOO (uses the `in-package` designator)
     P:FOO (looks in package P)
+    P::FOO (looks in package P)
     :FOO (keyword)
 
   "
-  ;; TODO: add support for:
-  ;;   P::FOO
-  (flet ((split-string (s delim)
-           (let ((idx (position delim s)))
-             (if idx
-               (cons (subseq s 0 idx)
-                     (subseq s (1+ idx)))
-               (cons nil s)))))
-    (destructuring-bind (package-name . symbol-name)
-        (split-string (string-upcase name) #\:)
-      (let ((package
-              (cond
-                ((null package-name) (parse-in-package in-package)) ; no : at all
-                ((string= "" package-name) (find-package "KEYWORD")) ; :keyw
-                (t (find-package package-name))))) ; pack:sym
-        (when package
-          (find-symbol symbol-name package))))))
+  (let ((package (parse-symbol-designator-package symbol-designator in-package))
+        (name (parse-symbol-designator-name symbol-designator)))
+    (when (and name package)
+      (find-symbol name package))))
 
 
 (define-middleware wrap-documentation "documentation" message
--- a/src/utils.lisp	Sun Aug 21 12:04:31 2016 +0000
+++ b/src/utils.lisp	Sun Aug 21 12:21:26 2016 +0000
@@ -50,7 +50,6 @@
   (apply #'format *log* args)
   (force-output *log*))
 
-
 (defun respond (message response)
   "Respond to `message` with the `response` map.
 
@@ -71,6 +70,6 @@
 ;                 :collect (list key value))))
 
 (defun parse-in-package (in-package)
-  (if (null in-package)
+  (if (or (null in-package) (string= in-package ""))
     *package*
     (or (find-package (read-from-string in-package)) *package*)))