Loose changes

This commit is contained in:
Ian Keane 2020-02-25 06:06:49 -05:00
parent 1cb167b597
commit 612c72bae1
57 changed files with 8904 additions and 80 deletions

View file

@ -0,0 +1 @@
*~

View file

@ -0,0 +1,19 @@
Copyright (c) 2010 Zachary Beane
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,8 @@
Quickproject creates the skeleton of a Common Lisp project.
For full documentation, see doc/index.html.
Quickproject is licensed under the MIT license; see LICENSE.txt for
details.
For questions or comments, please email Zach Beane <xach@xach.com>.

View file

@ -0,0 +1,12 @@
# (#| TMPL_VAR name |#)
### _(#| TMPL_VAR author |#)_
This is a project to do ... something.
## License
(#| TMPL_VAR license |#)
(#| TMPL_IF copyright |#)
(#| TMPL_VAR copyright |#)
(#| /TMPL_IF |#)

View file

@ -0,0 +1,5 @@
;;;; (#| TMPL_VAR name |#).lisp(#| TMPL_IF copyright |#)
;;
;;;; (#| TMPL_VAR copyright |#)(#| /TMPL_IF |#)
(in-package #:(#| TMPL_VAR name |#))

View file

@ -0,0 +1,6 @@
;;;; package.lisp(#| TMPL_IF copyright |#)
;;
;;;; (#| TMPL_VAR copyright |#)(#| /TMPL_IF |#)
(defpackage #:(#| TMPL_VAR name |#)
(:use #:cl))

View file

@ -0,0 +1,13 @@
;;;; (#| TMPL_VAR name |#).asd(#| TMPL_IF copyright |#)
;;
;;;; (#| TMPL_VAR copyright |#)(#| /TMPL_IF |#)
(asdf:defsystem #:(#| TMPL_VAR name |#)
:description "Describe (#| TMPL_VAR name |#) here"
:author "(#| TMPL_VAR author |#)"
:license "(#| TMPL_VAR license |#)"
:version "0.0.1"
:serial t(#| TMPL_IF depends-on |#)
:depends-on (#| TMPL_VAR dependencies-string |#)(#| /TMPL_IF |#)
:components ((:file "package")
(:file "(#| TMPL_VAR name |#)")))

View file

@ -0,0 +1,19 @@
Copyright (c) 2012 Zachary Beane
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,265 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel='stylesheet' type='text/css' href='style.css'>
<title>Quickproject - create a Common Lisp project skeleton</title>
</head>
<body>
<div id='content'>
<h2>Quickproject - create a Common Lisp project skeleton</h2>
<p>Quickproject is a library for creating a Common Lisp project
skeleton. It is available under a BSD-style license;
see <a href='LICENSE.txt'>LICENSE.txt</a> for details.
The latest version is 1.4.1, released on December 26th, 2019.
<p>Download
shortcut: <a href='http://www.xach.com/lisp/quickproject.tgz'>http://www.xach.com/lisp/quickproject.tgz</a>
<h2>Contents</h2>
<ul>
<li> <a href='#overview'>Overview</a>
<li> <a href='#examples'>Examples</a>
<li> <a href='#dictionary'>Dictionary</a>
<ul>
<li> <a href='#make-project'>make-project</a>
<li> <a href='#*author*'>*author*</a>
<li> <a href='#*include-copyright*'>*include-copyright*</a>
<li> <a href='#*license*'>*license*</a>
<li> <a href='#*template-directory*'>*template-directory*</a>
<li> <a href='#default-template-parameters'>default-template-parameters</a>
<li> <a href='#*template-parameter-functions*'>*template-parameter-functions*</a>
<li> <a href='#*after-make-project-hooks*'>*after-make-project-hooks*</a>
</ul>
<li> <a href='#feedback'>Feedback</a>
</ul>
<a name='overview'><h2>Overview</h2></a>
<p>Quickproject provides a quick way to make a Common Lisp
project. After creating a project, it extends the ASDF registry so
the project may be immediately loaded.
<a name='example'><h2>Examples</h2></a>
<pre class=code>
* <b>(quickproject:make-project #p"~/src/myproject/" :depends-on '(drakma cxml))</b>
"myproject"
* <b>(asdf:load-system "myproject")</b>
<i>load output</i>
</pre>
<pre class='code'>
* <b>(quickproject:make-project #p"~/src/websnarf/" :name "cl-websnarf")</b>
"cl-websnarf"
* <b>(directory #p"~/src/websnarf/*.*")</b>
(#p"~/src/websnarf/README.txt"
#p"~/src/websnarf/package.lisp"
#p"~/src/websnarf/cl-websnarf.asd"
#p"~/src/websnarf/cl-websnarf.lisp")
</pre>
<a name='dictionary'><h2>Dictionary</h2></a>
<p>The following symbols are exported from the <tt>quickproject</tt>
package.
<div class='item'>
<div class='type'><a name='make-project'>[Function]</a></div>
<div class='signature'>
<code class='name'>make-project</code>
<span class='args'>
<var>pathname</var> <code class='llkw'>&amp;key</code>
<var>depends-on</var>
<var>author</var>
<var>include-copyright</var>
<var>license</var>
<var>name</var>
<var>template-directory</var>
<var>template-parameters</var>
</span>
<span class='result'>=> <var>project-name</var></span>
</div>
<blockquote class='description'>
<p>Create the skeleton of a Common Lisp project
in <var>directory</var>. If given, <var>name</var> is used as the
name of the project. Otherwise, the name is taken from the last
component in
the <a href="http://l1sp.org/cl/pathname-directory">pathname-directory</a>
of the pathname. For example, the last directory component
of <tt>#p"src/lisp/myproject/"</tt> is "myproject".
<p>The project skeleton consists of the following files:
<ul>
<li> README.txt
<li> package.lisp &mdash; defines a package named after the project
<li> <var>name</var>.asd &mdash; defines an ASDF system named after
the project, with a <tt>:depends-on</tt> list as given in the
function call
<li> <var>name</var>.lisp
</ul>
<p>If provided, <var>author</var> and <var>license</var> are used
to initialize certain parts of the default files with extra
information. The default values are taken
from <a href='#*author*'><tt>*AUTHOR*</tt></a>
and <a href='#*license*'><tt>*LICENSE*</tt></a>, respectively.
<p>If provided, the boolean argument to <var>include-copyright</var>
will determine whether copyright notices will be printed in the
header of each file.
<p>If provided, each file in <var>template-directory</var> is
rewritten
with <a href="http://weitz.de/html-template/">HTML-TEMPLATE</a>
into the new directory. The options are as follows:
<ul>
<li> The template markers are <tt>(#|</tt> and <tt>|#)</tt>
<li> No escaping is done in template values
<li> Template parameters are created by
appending <var>template-parameters</var> with the lists returned by
calling each entry
in <a href='#*template-parameter-functions*'><tt>*TEMPLATE-PARAMETER-FUNCTIONS*</tt></a>
</ul>
<p>After rewriting templates, each element
in <a href='#*after-make-project-hooks*'><tt>*AFTER-MAKE-PROJECT-HOOKS*</tt></a>
is called.
<p>After the project has been created, its pathname is added
to <tt>ASDF:*CENTRAL-REGISTRY*</tt>, so the project is immediately
loadable via <tt>ASDF:LOAD-SYSTEM</tt>.
</blockquote>
</div>
<div class='item'>
<div class='type'><a name='*author*'>[Special variable]</a></div>
<div class='signature'>
<code class='name'>*author*</code>
</div>
<blockquote class='description'>
<p>This string is used to initialize the <tt>:author</tt> argument
in the project system definition. The default initial value
is <tt>"Your&nbsp;Name&nbsp;&lt;your.name@example.com>"</tt>.
</blockquote>
</div>
<div class='item'>
<div class='type'><a name='*include-copyright*'>[Special variable]</a></div>
<div class='signature'>
<code class='name'>*include-copyright*</code>
</div>
<blockquote class='description'>
<p>This variable is used to control whether a copyright notice (with
the author's name and the current year) should appear in the header
of each file.</tt>.
</blockquote>
</div>
<div class='item'>
<div class='type'><a name='*license*'>[Special variable]</a></div>
<div class='signature'>
<code class='name'>*license*</code>
</div>
<blockquote class='description'>
<p>This string is used to initialize the <tt>:description</tt>
argument in the project system definition. The default initial
value is <tt>"Specify&nbsp;license&nbsp;here"</tt>.
</blockquote>
</div>
<div class='item'>
<div class='type'><a name='*template-directory*'>[Special variable]</a></div>
<div class='signature'>
<code class='name'>*template-directory*</code>
</div>
<blockquote class='description'>
<p>If non-NIL, this variable should be bound to a pathname used as
the default value of <var>template-directory</var>
in <a href='#make-project'><tt>MAKE-PROJECT</tt></a>.
</blockquote>
</div>
<div class='item'>
<div class='type'><a name='default-template-parameters'>[Function]</a></div>
<div class='signature'>
<code class='name'>default-template-parameters</code>
<span class='args'>
</span>
<span class='result'>=> <var>parameters</var></span>
</div>
<blockquote class='description'>
<p>Return a plist with values for <tt>:name</tt>, <tt>:license</tt>,
and <tt>:author</tt> for the current project being created
via <a href='#make-project'><tt>MAKE-PROJECT</tt></a>. This
function is in the default value
of <a href='#*template-parameter-functions*'><tt>*TEMPLATE-PARAMETER-FUNCTIONS*</tt></a>.
</blockquote>
</div>
<div class='item'>
<div class='type'><a name='*template-parameter-functions*'>[Special variable]</a></div>
<div class='signature'>
<code class='name'>*template-parameter-functions*</code>
</div>
<blockquote class='description'>
<p>A list of functions that are called to produce template
parameters when rewriting templates
in <a href='#make-project'><tt>MAKE-PROJECT</tt></a>. Each
function is called with no arguments and should produce a list
of keyword/value pairs. The resulting lists are appended
together for use as template parameters
in <a href='http://weitz.de/html-template/#fill-and-print-template'><tt>HTML-TEMPLATE:FILL-AND-PRINT-TEMPLATE</tt></a>.
<p>The default value is <tt>(default-template-parameters)</tt>.
</blockquote>
</div>
<div class='item'>
<div class='type'><a name='*after-make-project-hooks*'>[Special variable]</a></div>
<div class='signature'>
<code class='name'>*after-make-project-hooks*</code>
</div>
<blockquote class='description'>
<p>A list of designators for functions to be called after a
project has been created. Each function should accept one required
argument, the pathname given
to <a href='#make-project'><tt>MAKE-PROJECT</tt></a>, and two
keyword arguments, <tt>:name</tt> and <tt>:depends-on</tt>, which
correspond to the name of the project (whether explicitly supplied
to <tt>MAKE-PROJECT</tt> or derived from the pathname) and the
<tt>:depends-on</tt> argument,
respectively. <tt>*default-pathname-defaults*</tt> is bound to the
newly created project pathname when hooks are called.
</blockquote>
</div>
<a name='feedback'><h2>Feedback</h2></a>
<p>For questions or comments about Quickproject, please email me, Zach
Beane &lt;<a href='mailto:xach@xach.com'>xach@xach.com</a>&gt;.
</div>
<br><br><br>
</body>

View file

@ -0,0 +1,83 @@
body {
margin-left: 4em;
font: medium/1.45em "Lucida Grande", "Trebuchet MS", "Bitstream Vera Sans", Verdana, Helvetica, sans-serif;
}
p.copyright {
font-size: 75%;
font-weight: bold;
}
#content {
margin-left: 4em;
margin-right: 4em;
max-width: 50em;
}
h2, h3 {
margin-bottom: 0em;
margin-top: 2em;
}
p.html {
margin-left: 1em;
font-family: monospace;
}
.type {
color: #999;
}
.signature {
color: #A01;
margin-left: 1em;
}
.signature span.result {
color: black;
}
.signature code.llkw {
font-family: monospace;
}
.signature span.result var {
color: #A01;
}
div.signature {
margin-left: 1.5em;
text-indent: -1.5em;
}
.signature code.name {
font-weight: bold;
}
.signature code {
font-family: sans-serif;
}
blockquote.description {
margin-left: 1em;
}
a[href] {
text-decoration: none;
border-bottom: dotted 1px #CCC;
color: #600;
}
a:hover[href] {
text-decoration: none;
border-bottom: solid 1px #F00;
color: #F00;
}
pre.code {
border: solid 1px #DDD;
padding: 0.5em;
background: #EEE;
}

View file

@ -0,0 +1,23 @@
;;;; package.lisp
(defpackage #:quickproject
(:documentation "The Quickproject package.")
(:use #:cl)
(:export #:make-project
#:*after-make-project-hooks*
#:*author*
#:*license*
#:*template-directory*
#:*include-copyright*
#:default-template-parameters
#:*template-parameter-functions*)
(:shadowing-import-from #:html-template
#:fill-and-print-template
#:*template-start-marker*
#:*template-end-marker*)
(:shadowing-import-from #:cl-fad
#:pathname-as-directory
#:walk-directory))
(in-package #:quickproject)

View file

@ -0,0 +1,12 @@
;;;; quickproject.asd
(asdf:defsystem #:quickproject
:description "Creates the skeleton of a new Common Lisp project"
:version "1.4.1"
:author "Zach Beane <xach@xach.com>"
:license "MIT"
:depends-on (#:cl-fad
#:html-template)
:serial t
:components ((:file "package")
(:file "quickproject")))

View file

@ -0,0 +1,144 @@
;;;; quickproject.lisp
(in-package #:quickproject)
(defvar *name*)
(setf (documentation '*name* 'variable)
"The name of the project currently being created.")
(defvar *template-directory* (asdf:system-relative-pathname :quickproject "default-template")
"A directory to use as a source of template files.")
(defvar *depends-on* nil
"Dependencies specified at project creation")
(defvar *author*
"Your Name <your.name@example.com>"
"Set this variable to your contact information.")
(defvar *license*
"Specify license here")
(defvar *include-copyright* nil ; This gives default behavior.
"Include a copyright notice at the top of files.")
(defun pathname-project-name (pathname)
"Return a project name based on PATHNAME by taking the last element
in the pathname-directory list. E.g. returns \"awesome-project\" for
#p\"src/awesome-project/\"."
(first (last (pathname-directory pathname))))
(defmacro with-new-file ((stream file) &body body)
"Like WITH-OPEN-FILE, but specialized for output to a file that must
not already exist."
`(with-open-file (,stream ,file
:direction :output
:if-exists :error)
(let ((*print-case* :downcase))
,@body)))
(defun current-year ()
(nth-value 5 (decode-universal-time (get-universal-time))))
(defvar *after-make-project-hooks* nil
"A list of functions to call after MAKE-PROJECT is finished making a
project. Each function is called with the same arguments passed to
MAKE-PROJECT, except that NAME is canonicalized if
necessary. *DEFAULT-PATHNAME-DEFAULTS* bound to the newly created
project directory.")
(defun matches-template-p (pathname template)
(and (equal (pathname-name pathname) (pathname-name template))
(equal (pathname-type pathname) (pathname-type template))))
(defun template-pathname->output-name (path)
(if (or (matches-template-p path "system.asd")
(matches-template-p path "application.lisp"))
(make-pathname :name *name* :defaults path)
path))
(defun rewrite-templates (template-directory target-directory parameters)
"Treat every file in TEMPLATE-DIRECTORY as a template file; fill it
out using PARAMETERS into a corresponding file in
TARGET-DIRECTORY. The rewriting uses HTML-TEMPLATE. The template start
marker is the string \"\(#|\" and the template end marker is the string
\"|#)\". Template vars are not modified or escaped when written."
(let ((*template-start-marker* "(#|")
(*template-end-marker* "|#)")
(html-template:*warn-on-creation* nil)
(html-template:*string-modifier* 'identity))
(setf template-directory (truename template-directory)
target-directory (truename target-directory))
(flet ((rewrite-template (pathname)
(let* ((relative-namestring
(enough-namestring pathname template-directory))
(target-pathname (template-pathname->output-name
(merge-pathnames relative-namestring
target-directory))))
(ensure-directories-exist target-pathname)
(with-open-file (stream
target-pathname
:direction :output
:if-exists :rename-and-delete)
(fill-and-print-template pathname
parameters
:stream stream)))))
(walk-directory template-directory #'rewrite-template))))
(defun default-template-parameters ()
"Return a plist of :NAME, :LICENSE, and :AUTHOR parameters."
(list :name *name*
:license *license*
:author *author*
:depends-on (mapcar
(lambda (sym)
(list :symbol sym :uninterned (format nil "#:~(~a~)" sym)))
*depends-on*)
:dependencies-string (format nil "(~{#:~(~a~)~^ ~})" *depends-on*)
:copyright (when *include-copyright*
(format nil "Copyright (c) ~D ~A~%" (current-year) *author*))))
(defvar *template-parameter-functions* (list 'default-template-parameters)
"A list of functions that return plists for use when rewriting
template files. The results of calling each function are appended
together to pass to FILL-AND-PRINT-TEMPLATE.")
(defun template-parameters (initial-parameters)
"Return all template parameters returned by calling each element in
*TEMPLATE-PARAMETER-FUNCTIONS*, appended together as a single plist."
(apply 'append initial-parameters
(mapcar 'funcall *template-parameter-functions*)))
(defun make-project (pathname &key
template-parameters
((:template-directory *template-directory*)
*template-directory*)
((:depends-on *depends-on*) *depends-on*)
((:author *author*) *author*)
((:license *license*) *license*)
(name (pathname-project-name pathname) name-provided-p)
((:include-copyright *include-copyright*) *include-copyright*))
"Create a project skeleton for NAME in PATHNAME. If DEPENDS-ON is provided,
it is used as the asdf defsystem depends-on list."
(check-type *depends-on* list)
(when (pathname-name pathname)
(warn "Coercing ~S to directory"
pathname)
(setf pathname (pathname-as-directory pathname))
(unless name-provided-p
(setf name (pathname-project-name pathname))))
(labels ((relative (file)
(merge-pathnames file pathname))
(nametype (type)
(relative (make-pathname :name name :type type))))
(ensure-directories-exist pathname)
(let ((*default-pathname-defaults* (truename pathname))
(*name* name))
(rewrite-templates *template-directory* *default-pathname-defaults*
(template-parameters template-parameters))
(pushnew *default-pathname-defaults* asdf:*central-registry*
:test 'equal)
(dolist (hook *after-make-project-hooks*)
(funcall hook pathname :depends-on *depends-on* :name name
:allow-other-keys t)))
name))