Skip to content

Instantly share code, notes, and snippets.

@rpgoldman
Created September 21, 2023 21:00
Show Gist options
  • Save rpgoldman/44a7b4e0645d9dafae699eb770553e3f to your computer and use it in GitHub Desktop.
Save rpgoldman/44a7b4e0645d9dafae699eb770553e3f to your computer and use it in GitHub Desktop.
Common Lisp Tempo Template definitions
;;; -*- Mode: emacs-lisp; -*-
;; templates are handy....
(require 'tempo)
(tempo-define-template
"read-only-slot"
(list
'(p "Slot name? " slot-name 'noinsert)
"(" '(s slot-name) 'n>
":initarg :" '(s slot-name) 'n>
":reader " '(s slot-name) 'n>
")"
))
(tempo-define-template
"read-write-slot"
(list
'(p "Slot name? " slot-name 'noinsert)
"(" '(s slot-name) 'n>
":initarg :" '(s slot-name) 'n>
":accessor " '(s slot-name) 'n>
")"
))
(tempo-define-template
"defclass"
(list
'(p "Class name? " class-name 'noinsert)
'(p "Superclasses? " superclass-list 'noinsert)
"(defclass " '(s class-name) " (" '(s superclass-list) ")" 'n>
"()" 'n> ;; slots
")" 'n>
))
(tempo-define-template
"defun"
(list
'(p "function name? " fun-name 'noinsert)
'(p "arguments? " arg-list 'noinsert)
"(defun " '(s fun-name) " (" '(s arg-list) ")" 'n>
'p ")" 'n>
'(prog1 nil (tempo-backward-mark))
))
(tempo-define-template
"define-condition"
(list
'(p "Condition name? " class-name 'noinsert)
'(p "Superclasses? " superclass-list 'noinsert)
"(define-condition " '(s class-name) " (" '(s superclass-list) ")" 'n>
"()" 'n> ;; slots
")" 'n>
))
(tempo-define-template
"defgeneric"
(list
"(defgeneric " '(p "function name? ")
" (" '(p "arguments? ") ")" 'n>
'(p "doc string?" docstring noinsert)
'(unless (equal (tempo-lookup-named 'docstring) "")
(list 'l "(:documentation \"" '(s docstring) "\")" 'n>))
")" 'n>
))
(tempo-define-template
"defgeneric-method"
(list "(:method "
'(p "Qualifier? ")
" (" '(p "arguments? ") ")" 'n>
")" 'n>))
(tempo-define-template
"defmethod"
(list
"(defmethod " '(p "function name? ")
" (" '(p "arguments? ") ")" 'n>
'(p "doc string?" docstring noinsert)
'(unless (equal (tempo-lookup-named 'docstring) "")
(list 'l "\"" '(s docstring) "\"" 'n>))
")" 'n>
))
(tempo-define-template
"defstruct"
(list
"(defstruct " '(p "structure name? ")
" (" '(p "arguments? ") ")" 'n>
"\"" '(p "doc string?") "\"" 'n>
")" 'n>
))
(tempo-define-template
"documentation"
(list
'(p "doc string?" docstr 'noinsert)
"(:documentation \""
'(s docstr)
"\")"
))
(tempo-define-template
"defvar"
(list
"(defvar " '(p "variable name? ") 'n>
'(p "initial value? ") 'n>
"\"" '(p "doc string?" ) "\")" 'n>
))
(tempo-define-template
"defpackage"
(list
"(defpackage " '(p "package name? ") 'n>
'(p "uses package (list or single package)? " uses noinsert)
'(let ((uses (first (read-from-string (tempo-lookup-named 'uses)))))
(cond ((null uses) nil)
((listp uses)
`(l "(:use" ,@(loop for x in uses
collect " "
collect (symbol-name x))
")"))
(t
`(l "(:use " (s uses) ")"))))
;; nicknames would be a nice addition...
")"
'n>
))
(tempo-define-template
"asdf-prefix"
(list
"(defpackage " ":" '(p "system name? " name) "-asd" 'n>
"(:use :common-lisp :asdf)" 'n>
")"
'n>
"(in-package " ":" '(s name) "-asd" ")" 'n>
"(defsystem " '(s name) 'n>
":depends-on ()" 'n>
":components ()" 'n>
")"
))
(tempo-define-template
"defstruct"
(list
'(p "Struct type name? " class-name 'noinsert)
"(defstruct " '(s class-name) 'n>
'n>;; slots
")" 'n>
))
(tempo-define-template
"in-package"
(list
'(p "Package name? " pkg-name 'noinsert)
"(in-package #:" '(s pkg-name) ")"
))
(tempo-define-template
"function-declaration"
(list
"(declaim" 'n>
"(ftype" 'n>
"(function "
'(p "function name? " fname t)
"(" '(p "argument types? ") ")" 'n>
"(values " '(p "return values? ") " &optional))" 'n>
'(s fname) "))" '>
))
(defun make-cl-tempo-map (map &optional map-key)
(unless map-key (setf map-key (kbd "C-c C-c")))
(let ((tempo-map (make-sparse-keymap "lisp-tempo-map")))
(define-key map map-key tempo-map)
(cl-template-populate-tempo-map tempo-map)))
(defun cl-template-populate-tempo-map (tempo-map)
(define-key tempo-map "r" 'tempo-template-read-only-slot)
(define-key tempo-map "w" 'tempo-template-read-write-slot)
(let ((defgeneric-submap (make-sparse-keymap "lisp-defgeneric-tempo-map")))
(define-key tempo-map "g" defgeneric-submap)
(define-key defgeneric-submap "g" 'tempo-template-defgeneric)
(define-key defgeneric-submap "m" 'tempo-template-defgeneric-method)
(define-key defgeneric-submap "d" 'tempo-template-documentation))
(define-key tempo-map "c" 'tempo-template-defclass)
(define-key tempo-map "C" 'tempo-template-define-condition)
(define-key tempo-map "p" 'tempo-template-defpackage)
(define-key tempo-map "d" 'tempo-template-documentation)
(define-key tempo-map "m" 'tempo-template-defmethod)
(define-key tempo-map "v" 'tempo-template-defvar)
(define-key tempo-map "a" 'tempo-template-asdf-prefix)
(define-key tempo-map "s" 'tempo-template-defstruct)
(define-key tempo-map "f" 'tempo-template-defun)
(define-key tempo-map "i" 'tempo-template-in-package)
)
(defun cl-template-populate-tempo-menu (parent-keymap)
"Add a submenu to the PARENT-KEYMAP for CL templates."
(easy-menu-define sly-cl-template-menu parent-keymap
"Menu of Common Lisp Templates"
'("CL Templates"
("Defclass helpers"
[ "New DEFCLASS " tempo-template-defclass]
["Add read-only slot" tempo-template-read-only-slot]
["Add read-write slot" tempo-template-read-write-slot]
["Add docstring" tempo-template-documentation]
)
("Defgeneric helpers"
[ "New DEFGENERIC " tempo-template-defgeneric]
[ "Internal method definition" tempo-template-defgeneric-method]
["Add docstring" tempo-template-documentation]
)
("Other Top level constructs"
["Define condition" tempo-template-define-condition]
["Define method" tempo-template-defmethod]
["Define variable" tempo-template-defvar]
["Define function" tempo-template-defun]
["Define structure" tempo-template-defstruct]
)
("Misc"
["ASDF file header" tempo-template-asdf-prefix]
["IN-PACKAGE" tempo-template-in-package]))))
(provide 'cl-templates)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment