Coverage report: /home/ellis/comp/core/app/skel/core/obj.lisp
Kind | Covered | All | % |
expression | 11 | 293 | 3.8 |
branch | 2 | 28 | 7.1 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;; skel/core/obj.lisp --- Skel Objects
3
;; SKEL classes and methods
6
(in-package :skel/core/obj)
10
(:documentation "Base class for skeleton objects."))
12
(declaim (inline sk-slot-name sk-class-name))
13
(defun sk-class-name (self &optional downcase)
14
(let* ((class-name (string (class-name (class-of self))))
15
(match (search "SK-" class-name :test 'equal :start1 0 :end1 3))
23
(defun sk-slot-name (self &optional downcase)
24
(keywordicate (sk-class-name self downcase)))
26
(defmethod sk-new ((self t) &rest initargs)
27
(apply #'make-instance self initargs))
29
(defmethod print-object ((self skel) stream)
30
(print-unreadable-object (self stream)
31
(format stream "~A :ID ~A" (sk-class-name self t) (format-sxhash (id self)))))
33
(defmethod initialize-instance :around ((self skel) &rest initargs &key &allow-other-keys)
34
;; TODO 2023-09-10: make fast
35
(unless (getf initargs :id)
36
(setf (id self) (sxhash self)))
40
;; TODO 2023-09-11: research other hashing strategies - maybe use the
41
;; sxhash as a nonce for UUID
42
;; note that the sk-meta class does not inherit from skel or ast.
45
((name :initarg :name :initform nil :type (or null string) :accessor name)
46
(path :initarg :path :initform nil :type (or null pathname) :accessor path)
47
(author :initform "" :initarg :author :type contact-designator :accessor sk-author)
48
(version :initform "" :initarg :version :type string :accessor sk-version)
49
(tags :initform nil :initarg :tags :accessor sk-tags)
50
(description :initarg :description :initform nil :type (or null string) :accessor sk-description)
51
(license :initarg :license :type license-designator :accessor sk-license))
52
(:documentation "Skel Meta class."))
54
(defmethod print-object ((self sk-meta) stream)
55
(print-unreadable-object (self stream)
56
(format stream "~A ~A :path ~A" (sk-class-name self t) (name self) (path self))
57
;; (unless (sequence:emptyp (sk-version self))
58
;; (format stream " :version ~A" (sk-version self)))
59
(format stream " :id ~A" (format-sxhash (id self)))))
61
(defun sk-init (class &rest initargs)
62
(apply #'make-instance class initargs))
64
(defmacro sk-init-dir (class &rest initargs)
65
`(let ((self (sk-init ',class ,@initargs)))
66
(unless (getf ',initargs :path)
67
(setf (path self) (sb-posix:getcwd)))
70
(defmacro sk-init-file (class &rest initargs)
71
`(let ((self (sk-init ',class ,@initargs)))
72
(unless (getf ',initargs :path)
73
(setf (path self) *default-skelfile*))
77
(defconfig sk-config (skel ast)
78
((vc :initform *default-vc-kind* :initarg :vc :type (or vc-repo vc-designator) :accessor sk-vc)
79
(store :initform skel-store :initarg :store :type pathname :accessor sk-store)
80
(stash :initform skel-stash :initarg :stash :type pathname :accessor sk-stash)
81
(cache :initform skel-cache :initarg :cache :type pathname :accessor sk-cache)
82
(data :initform skel-data :initarg :data :type pathname :accessor sk-data)
83
(scripts :initform nil :initarg :scripts :type (or pathname list (vector pathname)) :accessor sk-scripts)
84
(license :initform nil :initarg :license :type license-designator :accessor sk-license)
85
(log-level :initform *log-level* :initarg :log-level :type log-level-designator)
86
(fmt :initform :pretty :initarg :fmt :type symbol)
87
(auto-insert :initform nil :initarg :auto-insert :type form))
88
(:documentation "Root configuration class for the SKEL system. This class doesn't need to be exposed externally, but specifies all shared fields of SK-*-CONFIG types."))
90
(defmethod sk-new ((self (eql :config)) &rest args &key (type :user))
93
(:user 'sk-user-config)
94
(:system 'sk-system-config)
96
(apply #'sk-new self args))
98
(defmethod make-config ((self (eql :skel)) &rest args)
99
(apply 'make-instance 'sk-config args))
101
(declaim (inline bound-string-p sk-dir))
102
(defun bound-string-p (o s) (and (slot-boundp o s) (stringp (slot-value o s))))
104
(let ((str (directory-namestring (path o))))
105
(if (sb-sequence:emptyp str)
106
*default-pathname-defaults*
109
(defmethod load-ast ((self sk-config))
110
;; internal ast is never tagged
111
(with-slots (ast) self
113
;; ast is valid, modify object, set ast nil
115
(sb-int:doplist (k v) ast
116
(when-let ((s (find-sk-symbol k)))
117
(setf (slot-value self s) v))) ;; needs to be the correct package
118
(when (bound-string-p self 'stash) (setf (sk-stash self) (merge-pathnames (sk-stash self) (sk-dir self))))
119
(when (bound-string-p self 'store) (setf (sk-store self) (merge-pathnames (sk-store self) (sk-dir self))))
120
(when (bound-string-p self 'cache) (setf (sk-cache self) (sk-cache self)))
121
(when (bound-string-p self 'data) (setf (sk-data self) (sk-data self)))
123
(if (bound-string-p self 'scripts)
124
(if-let* ((path (probe-file (pathname (the simple-string (sk-scripts self))))))
125
(setf (sk-scripts self)
126
(if (directory-path-p path)
129
(warn! (format nil "ignoring missing scripts directory: ~A" (sk-scripts self)))))
130
(unless *keep-ast* (setf (ast self) nil))
132
;; invalid ast, signal error
133
(invalid-skel-ast ast))))
135
(defmethod build-ast ((self sk-config) &key (nullp nil) (exclude '(ast id author version user)))
143
(defmethod sk-write-file ((self sk-config)
144
&key (path *default-skelfile*)
149
(build-ast self :nullp nullp)
151
(with-open-file (out path
154
:if-does-not-exist :create)
156
(make-source-header-comment
160
:description (sk-description self)
161
:opts '("mode:skel;"))
163
(write-ast self out :fmt fmt))
164
(unless *keep-ast* (setf (ast self) nil))))
166
(defmethod write-ast ((self sk-config) stream &key (pretty t) (case :downcase) (fmt :pretty))
169
(if (listp (ast self))
170
(with-open-stream (st stream)
171
(loop for (k v . rest) on (ast self)
173
unless (or (null v) (null k))
175
(write k :stream stream :pretty pretty :case case :readably t :array t :escape t)
176
(write-char #\space st)
177
(if (or (eq (type-of v) 'skel) (subtypep (type-of v) 'structure-object))
178
(write-ast v stream :fmt fmt)
179
(write v :stream stream :pretty pretty :case case :readably t :array t :escape t))
180
(write-char #\newline st)))
182
(:canonical (write (ast self) :stream stream :pretty pretty :case case :readably t :array t :escape t))))
184
(defclass sk-system-config (sk-config sk-meta) ())
186
(defun default-sk-system-config ()
187
(make-instance 'sk-system-config))
189
(defclass sk-user-config (sk-config sk-meta)
190
((user :initarg :user :type string :accessor sk-user :initform *user*)
191
(name :initarg :name :type string :accessor name)
192
(email :initarg :email :type string :accessor sk-email))
193
(:documentation "User configuration object, typically written to ~/.skelrc."))
195
(defun default-sk-user-config () (make-instance 'sk-user-config))
197
(declaim (type (or sk-user-config null) *skel-user-config*))
198
(declaim (type (or sk-system-config null) *skel-system-config*))
199
(defvar *skel-user-config* nil)
200
(defvar *skel-system-config* nil)