Initial commit
This commit is contained in:
commit
174f6e5452
4 changed files with 101 additions and 0 deletions
8
README.md
Normal file
8
README.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# syrup: assorted syntactic sugar for Lisp
|
||||||
|
|
||||||
|
Syrup is a simple package providing syntax enhancements to Common Lisp.
|
||||||
|
|
||||||
|
Right now it doesn't do much, but I'll add new features as I think of them.
|
||||||
|
|
||||||
|
- `#^sym` to export a symbol inline
|
||||||
|
- `[]` and `{}` can be used in place of normal parentheses
|
25
superfluous-parentheses.el
Normal file
25
superfluous-parentheses.el
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
;;; superfluous-parentheses --- Emacs support for [] and {} in lisp-mode
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
(defun superfluous-modify-font-lock-keywords (rule-table)
|
||||||
|
(dolist (rule rule-table)
|
||||||
|
(when (and (consp rule) (stringp (car rule)))
|
||||||
|
(when (string-prefix-p "(" (car rule))
|
||||||
|
(rplaca rule (concat "\\s(" (substring (car rule) 1)))))))
|
||||||
|
|
||||||
|
(add-hook! lisp-mode
|
||||||
|
(modify-syntax-entry ?\[ "(]" lisp-mode-syntax-table)
|
||||||
|
(modify-syntax-entry ?\] ")[" lisp-mode-syntax-table)
|
||||||
|
(modify-syntax-entry ?\{ "(}" lisp-mode-syntax-table)
|
||||||
|
(modify-syntax-entry ?\} "){" lisp-mode-syntax-table)
|
||||||
|
(superfluous-modify-font-lock-keywords lisp-cl-font-lock-keywords-1)
|
||||||
|
(superfluous-modify-font-lock-keywords lisp-cl-font-lock-keywords-2)
|
||||||
|
(superfluous-modify-font-lock-keywords lisp-cl-font-lock-keywords))
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; This package modifies the lisp-mode syntax table and font-lock keywords to
|
||||||
|
;; provide proper support for using square brackets and curly braces in Common
|
||||||
|
;; Lisp code, as per superfluous-parentheses.
|
||||||
|
|
||||||
|
(provide 'superfluous-parentheses)
|
||||||
|
;;; superfluous-parentheses.el ends here
|
7
syrup.asd
Normal file
7
syrup.asd
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
(asdf:defsystem "syrup"
|
||||||
|
:description "Assorted syntactic sugar for Lisp."
|
||||||
|
:version "1.0"
|
||||||
|
:author "~keith <keith@keithhacks.cyou>"
|
||||||
|
:homepage "https://bytes.keithhacks.cyou/keith/syrup"
|
||||||
|
:license "Public Domain/CC0"
|
||||||
|
:components ((:file "syrup")))
|
61
syrup.lisp
Normal file
61
syrup.lisp
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
(defpackage #:syrup
|
||||||
|
(:use #:cl))
|
||||||
|
(in-package #:syrup)
|
||||||
|
|
||||||
|
(define-condition simple-reader-error (simple-condition reader-error) ())
|
||||||
|
|
||||||
|
;; #^ - Inline symbol export macro
|
||||||
|
;; Use #^SYMBOL or #^(SYMBOL) to export a symbol at the location it's defined.
|
||||||
|
(defun read-exported-symbol (stream char arg)
|
||||||
|
"Read a symbol (optionally wrapped in parens) and export it"
|
||||||
|
(declare (ignore char arg))
|
||||||
|
(let ((sym (read stream t nil t)))
|
||||||
|
(when (and (consp sym) (not (cdr sym)))
|
||||||
|
(setf sym (car sym))) ;; allow wrapping symbol in parens
|
||||||
|
(unless (symbolp sym)
|
||||||
|
(error 'simple-reader-error
|
||||||
|
:stream stream
|
||||||
|
:format-control "Not a symbol: ~S"
|
||||||
|
:format-arguments (list sym)))
|
||||||
|
(export sym)
|
||||||
|
sym))
|
||||||
|
(set-dispatch-macro-character #\# #\^ #'read-exported-symbol)
|
||||||
|
|
||||||
|
;; Use [] and {} like normal parentheses
|
||||||
|
;; NOTE: You'll have to add superfluous-parentheses.el to Emacs to get it to recognize this syntax
|
||||||
|
(defun read-bracketed-list (stream begin-char)
|
||||||
|
(let* ((end-char (cond ((char= begin-char #\[) #\])
|
||||||
|
((char= begin-char #\{) #\})
|
||||||
|
(t (error 'simple-reader-error
|
||||||
|
:stream stream
|
||||||
|
:format-control "Invalid bracket ~S"
|
||||||
|
:format-arguments (list begin-char)))))
|
||||||
|
(list-body (loop for next-char = (peek-char t stream t nil t)
|
||||||
|
until (or (char= next-char end-char) (char= next-char #\.))
|
||||||
|
collect (read stream t nil t)))
|
||||||
|
(last-char (read-char stream t nil t))) ;; discard the last peeked character
|
||||||
|
(cond ((char= last-char end-char) list-body)
|
||||||
|
((char= last-char #\.)
|
||||||
|
(unless list-body
|
||||||
|
(error 'simple-reader-error
|
||||||
|
:stream stream
|
||||||
|
:format-control "Nothing before . in list."
|
||||||
|
:format-arguments nil))
|
||||||
|
;; set the CDR of the list
|
||||||
|
(rplacd (last list-body) (read stream t nil t))
|
||||||
|
;; skip past whitespace
|
||||||
|
(peek-char t stream t nil t)
|
||||||
|
(unless (char= (read-char stream t nil t) end-char)
|
||||||
|
(error 'simple-reader-error
|
||||||
|
:stream stream
|
||||||
|
:format-control "Multiple objects after . in list."
|
||||||
|
:format-arguments nil))
|
||||||
|
list-body)
|
||||||
|
(t (error 'simple-reader-error
|
||||||
|
:stream stream
|
||||||
|
:format-control "Expected ~S or ., but got ~S."
|
||||||
|
:format-arguments (list end-char last-char))))))
|
||||||
|
(set-macro-character #\[ #'read-bracketed-list)
|
||||||
|
(set-macro-character #\] (get-macro-character #\)))
|
||||||
|
(set-macro-character #\{ #'read-bracketed-list)
|
||||||
|
(set-macro-character #\} (get-macro-character #\)))
|
Loading…
Reference in a new issue