2018-07-11

# glyphs

A little experiment in reducing verbosity in Common Lisp, inspired by BODOL (https://github.com/bodil/BODOL - no affiliation).

Update: Now that it's in quicklisp, simply:

``(ql:quickload :glyphs)``

## Examples

### Factorial example with glyphs function macro:

glyphs:

``````(? factorial
0 ? 1
? ? (* ? (factorial (1- ?))))``````

vs.:

``````(defun factorial (x)
(cond ((equal x 0) 1)
(x (* x (factorial (1- x))))))``````

result:

``````(factorial 8)
40320``````

### Type safety with factorial

``````(? factorial
0 ? 1
(and (numberp ?) (> ? 0)) ? (* ? (factorial (1- ?)))
? ? (error "Non-numbers (or negatives) don't work real well with factorials!"))``````

vs.:

``````(defun factorial (x)
(cond ((equal x 0) 1)
((and (numberp x) (> x 0)) (* x (factorial (1- x))))
(t (error "Non-numbers (or negatives) don't work real well with factorials!"))))``````

### Built in type safety with factorial

``````(?? factorial (integer ? integer)
0 ? 1
? ? (* ? (factorial (1- ?))))``````

### Reverse a list

glyphs:

``````(? reverse*
(cdr ?) ? (append (reverse* (cdr ?)) `(,(car ?)))
? ? ?)``````

### Map with glyphs lambda macro to compare strings and do a side effect

glyphs:

``````(mapcar (? "cat" ? (print "Cats rock")
"dog" ? (print "Dogs do too!")) '("cat" "dog" "mouse"))``````

vs.:

``````(mapcar (lambda (x)
(cond ((equal x "cat") (print "Cats rock"))
((equal x "dog") (print "Dogs do too!")) '("cat" "dog" "mouse"))))``````

result:

``````"Cats rock"
"Dogs do too!"
NIL``````

## Comparison based on passed in conditionals

glyphs:

``````(? double-odds-half-evens
(oddp ?) ? (* x 2)
(evenp ?) ? (/ x 2))``````

vs.:

``````(defun double-odds-half-evens (x)
(cond ((oddp x) (* x 2))
((evenp x) (/ x 2))))``````

result:

``````(double-odds-half-evens 4)
2
(double-odds-half-evens 3)
6``````

### Using multiple values by including special variables in the statement

You can use multiple values by prefixing a variable in the statement portion of the code with either a '?' or an '?'.

glyphs:

``(mapcar (? ? ? (+ ? ?b ?c)) '(1 2 3) '(4 5 6) '(7 8 9))``

vs.:

``(mapcar (lambda (a b c) (+ a b c)) '(1 2 3) '(4 5 6) '(7 8 9))``

result:

``(12 15 18)``

## Fast matching based on regex strings

Make sure to use the readtable that comes with it first:

``(in-readtable glyphs:syntax)``

Or these little readtable shortcuts will not work.

glyphs:

``````(? any-cats?
~"cat"~ ? (print "yes!"))``````

vs.:

``````(defun any-cats? (x)
(when (cl-ppcre:scan "cat" x)
(print "yes!")))``````

result:

``````(any-cats? "I see some cats")
"yes!"``````

## Easy regex replaces on matching strings

glyphs:

``````(? no-cats
~"(were|cat)"~ ? |"dog"|)``````

vs.:

``````(defun no-cats (x)
(let ((regex "(were|cat)"))
(when (cl-ppcre:scan regex x)
(cl-ppcre:regex-replace-all regex x "dog"))))``````

result:

``````(no-cats "there were dogs and there were cats")
"there dog dogs and there dog dogs"``````

# Currently used glyphs and bindings for them (more to come)

## Emacs bindings

``````;; Keybindings for glyphs
(global-set-key (kbd "M-l") (lambda () (interactive) (insert "\u03bb"))) ; ? lambda
(global-set-key (kbd "M-f") (lambda () (interactive) (insert "\u0192"))) ; ? function
(global-set-key (kbd "M--") (lambda () (interactive) (insert "\u2192"))) ; ? right arrow
(global-set-key (kbd "M-a") (lambda () (interactive) (insert "\u03b1"))) ; ? alpha
(global-set-key (kbd "M-y") (lambda () (interactive) (insert "\u03c8"))) ; ? psi``````

## Vim bindings

``````" Keybindings for glyphs
:inoremap <A-l> <C-v>u3bb<Space>   ; ? lambda
:inoremap <A-f> <C-v>u192<Space>   ; ? function
:inoremap <A--> <C-v>u2192<Space>  ; ? right arrow
:inoremap <A-a> <C-v>u03b1<Space>  ; ? alpha
:inoremap <A-y> <C-v>u03c8<Space>  ; ? psi``````

## Mac OS X keybindings

``````{
"~l" = ("insertText:", "\U03BB"); /* alt + l ~> ? lambda */
"~f" = ("insertText:", "\U0192"); /* alt + f ~> ? function */
"~-" = ("insertText:", "\U2192"); /* alt + - ~> ? right arrow */
"~a" = ("insertText:", "\U03b1"); /* alt + a ~> ? alpha */
"~y" = ("insertText:", "\U03c8"); /* alt + y ~> ? psi */
}``````

## StumpWM keybindings

``````(defmacro defkeys-top (&rest keys)
(let ((ks (mapcar #'(lambda (k) (cons 'defkey-top k)) keys)))
`(progn ,@ks)))

(defcommand xdo-lambda () ()
(run-shell-command "xdotool type ?"))
(defcommand xdo-fn () ()
(run-shell-command "xdotool type ?"))
(defcommand xdo-alpha () ()
(run-shell-command "xdotool type ?"))
(defcommand xdo-arrow () ()
(run-shell-command "xdotool type ?"))

(defkeys-top
("s-l" "xdo-lambda")
("s-f" "xdo-fn")
("s--" "xdo-arrow")
("s-a" "xdo-alpha"))``````

If you're absolutely opposed to non-ascii characters, you can use:

``````? == /.
? == f
? == ->``````